summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 04:23:18 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 04:23:18 +0000
commit16527d165de55f2727f55b752b30d44a7e61e927 (patch)
tree0840ee6e0e109a9e85f0d80ff36f92587c6a5538 /tests
parentReleasing progress-linux version 2.1.30-2.1~progress7.99u1. (diff)
downloadlibyang2-16527d165de55f2727f55b752b30d44a7e61e927.tar.xz
libyang2-16527d165de55f2727f55b752b30d44a7e61e927.zip
Merging upstream version 2.1.148.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/CMakeLists.txt2
-rw-r--r--tests/tool_i.tcl156
-rw-r--r--tests/tool_ni.tcl141
-rw-r--r--tests/utests/basic/test_common.c2
-rw-r--r--tests/utests/basic/test_context.c32
-rw-r--r--tests/utests/basic/test_hash_table.c132
-rw-r--r--tests/utests/basic/test_inout.c6
-rw-r--r--tests/utests/basic/test_json.c443
-rw-r--r--tests/utests/basic/test_plugins.c2
-rw-r--r--tests/utests/basic/test_set.c2
-rw-r--r--tests/utests/basic/test_xml.c2
-rw-r--r--tests/utests/basic/test_xpath.c204
-rw-r--r--tests/utests/data/test_diff.c258
-rw-r--r--tests/utests/data/test_new.c63
-rw-r--r--tests/utests/data/test_parser_json.c172
-rw-r--r--tests/utests/data/test_parser_xml.c226
-rw-r--r--tests/utests/data/test_printer_xml.c3
-rw-r--r--tests/utests/data/test_tree_data.c35
-rw-r--r--tests/utests/data/test_validation.c93
-rw-r--r--tests/utests/extensions/test_metadata.c24
-rw-r--r--tests/utests/extensions/test_nacm.c8
-rw-r--r--tests/utests/extensions/test_schema_mount.c121
-rw-r--r--tests/utests/extensions/test_structure.c14
-rw-r--r--tests/utests/extensions/test_yangdata.c20
-rw-r--r--tests/utests/node/list.c53
-rw-r--r--tests/utests/schema/test_printer_tree.c119
-rw-r--r--tests/utests/schema/test_schema.c273
-rw-r--r--tests/utests/schema/test_tree_schema_compile.c890
-rw-r--r--tests/utests/schema/test_yang.c12
-rw-r--r--tests/utests/schema/test_yin.c8
-rw-r--r--tests/utests/types/binary.c42
-rw-r--r--tests/utests/types/bits.c97
-rw-r--r--tests/utests/types/identityref.c50
-rw-r--r--tests/utests/types/instanceid.c47
-rw-r--r--tests/utests/types/int8.c37
-rw-r--r--tests/utests/types/leafref.c66
-rw-r--r--tests/utests/types/string.c60
-rw-r--r--tests/utests/types/union.c73
-rw-r--r--tests/utests/types/yang_types.c90
-rw-r--r--tests/utests/utests.h131
-rw-r--r--tests/yanglint/CMakeLists.txt36
-rw-r--r--tests/yanglint/README.md107
-rw-r--r--tests/yanglint/common.tcl114
-rw-r--r--tests/yanglint/data/modaction.xml8
-rw-r--r--tests/yanglint/data/modaction_ds.xml5
-rw-r--r--tests/yanglint/data/modaction_nc.xml13
-rw-r--r--tests/yanglint/data/modaction_reply.xml8
-rw-r--r--tests/yanglint/data/modaction_reply_nc.xml4
-rw-r--r--tests/yanglint/data/modconfig.xml4
-rw-r--r--tests/yanglint/data/modconfig2.xml3
-rw-r--r--tests/yanglint/data/modconfig_ctx.xml13
-rw-r--r--tests/yanglint/data/moddatanodes.xml17
-rw-r--r--tests/yanglint/data/moddefault.xml4
-rw-r--r--tests/yanglint/data/modimp_type_ctx.xml13
-rw-r--r--tests/yanglint/data/modleaf.djson3
-rw-r--r--tests/yanglint/data/modleaf.dxml1
-rw-r--r--tests/yanglint/data/modleaf.xml1
-rw-r--r--tests/yanglint/data/modleafref.xml2
-rw-r--r--tests/yanglint/data/modleafref2.xml2
-rw-r--r--tests/yanglint/data/modmandatory.xml3
-rw-r--r--tests/yanglint/data/modmandatory_invalid.xml3
-rw-r--r--tests/yanglint/data/modmerge.xml4
-rw-r--r--tests/yanglint/data/modmerge2.xml3
-rw-r--r--tests/yanglint/data/modmerge3.xml3
-rw-r--r--tests/yanglint/data/modnotif.xml5
-rw-r--r--tests/yanglint/data/modnotif2.xml3
-rw-r--r--tests/yanglint/data/modnotif2_nc.xml6
-rw-r--r--tests/yanglint/data/modnotif_ds.xml1
-rw-r--r--tests/yanglint/data/modnotif_nc.xml8
-rw-r--r--tests/yanglint/data/modoper_leafref_action.xml8
-rw-r--r--tests/yanglint/data/modoper_leafref_action_reply.xml8
-rw-r--r--tests/yanglint/data/modoper_leafref_ds.xml9
-rw-r--r--tests/yanglint/data/modoper_leafref_notif.xml3
-rw-r--r--tests/yanglint/data/modoper_leafref_notif2.xml8
-rw-r--r--tests/yanglint/data/modoper_leafref_notif_err.xml7
-rw-r--r--tests/yanglint/data/modoper_leafref_rpc.xml3
-rw-r--r--tests/yanglint/data/modoper_leafref_rpc_reply.xml5
-rw-r--r--tests/yanglint/data/modrpc.xml3
-rw-r--r--tests/yanglint/data/modrpc_nc.xml6
-rw-r--r--tests/yanglint/data/modrpc_reply.xml5
-rw-r--r--tests/yanglint/data/modrpc_reply_nc.xml6
-rw-r--r--tests/yanglint/data/modsm.xml3
-rw-r--r--tests/yanglint/data/modsm2.xml4
-rw-r--r--tests/yanglint/data/modsm_ctx_ext.xml20
-rw-r--r--tests/yanglint/data/modsm_ctx_main.xml17
-rw-r--r--tests/yanglint/interactive/add.test59
-rw-r--r--tests/yanglint/interactive/all.tcl15
-rw-r--r--tests/yanglint/interactive/clear.test53
-rw-r--r--tests/yanglint/interactive/completion.test69
-rw-r--r--tests/yanglint/interactive/data_default.test41
-rw-r--r--tests/yanglint/interactive/data_format.test23
-rw-r--r--tests/yanglint/interactive/data_in_format.test21
-rw-r--r--tests/yanglint/interactive/data_merge.test33
-rw-r--r--tests/yanglint/interactive/data_not_strict.test25
-rw-r--r--tests/yanglint/interactive/data_operational.test86
-rw-r--r--tests/yanglint/interactive/data_present.test25
-rw-r--r--tests/yanglint/interactive/data_type.test140
-rw-r--r--tests/yanglint/interactive/data_xpath.test57
-rw-r--r--tests/yanglint/interactive/debug.test33
-rw-r--r--tests/yanglint/interactive/extdata.test63
-rw-r--r--tests/yanglint/interactive/feature.test37
-rw-r--r--tests/yanglint/interactive/list.test34
-rw-r--r--tests/yanglint/interactive/load.test45
-rw-r--r--tests/yanglint/interactive/ly.tcl81
-rw-r--r--tests/yanglint/interactive/modcwd.yang4
-rw-r--r--tests/yanglint/interactive/print.test77
-rw-r--r--tests/yanglint/interactive/searchpath.test24
-rw-r--r--tests/yanglint/modules/ietf-interfaces.yang725
-rw-r--r--tests/yanglint/modules/ietf-ip.yang758
-rw-r--r--tests/yanglint/modules/ietf-netconf-acm.yang411
-rw-r--r--tests/yanglint/modules/ietf-netconf-with-defaults@2011-06-01.yang140
-rw-r--r--tests/yanglint/modules/ietf-netconf@2011-06-01.yang934
-rw-r--r--tests/yanglint/modules/modaction.yang26
-rw-r--r--tests/yanglint/modules/modconfig-augment.yang15
-rw-r--r--tests/yanglint/modules/modconfig.yang17
-rw-r--r--tests/yanglint/modules/moddatanodes.yang31
-rw-r--r--tests/yanglint/modules/moddefault.yang19
-rw-r--r--tests/yanglint/modules/modextleafref.yang24
-rw-r--r--tests/yanglint/modules/modfeature.yang7
-rw-r--r--tests/yanglint/modules/modimp-cwd.yang8
-rw-r--r--tests/yanglint/modules/modimp-path.yang8
-rw-r--r--tests/yanglint/modules/modimp-type.yang12
-rw-r--r--tests/yanglint/modules/modinclude.yang9
-rw-r--r--tests/yanglint/modules/modleaf.yang8
-rw-r--r--tests/yanglint/modules/modleafref.yang14
-rw-r--r--tests/yanglint/modules/modmandatory.yang14
-rw-r--r--tests/yanglint/modules/modmerge.yang21
-rw-r--r--tests/yanglint/modules/modmust.yang13
-rw-r--r--tests/yanglint/modules/modnotif.yang19
-rw-r--r--tests/yanglint/modules/modoper-leafref.yang68
-rw-r--r--tests/yanglint/modules/modpath.yang4
-rw-r--r--tests/yanglint/modules/modrpc.yang19
-rw-r--r--tests/yanglint/modules/modsm-augment.yang15
-rw-r--r--tests/yanglint/modules/modsm.yang13
-rw-r--r--tests/yanglint/modules/modsub.yang8
-rw-r--r--tests/yanglint/modules/modtypedef.yang8
-rw-r--r--tests/yanglint/non-interactive/all.tcl15
-rw-r--r--tests/yanglint/non-interactive/data_default.test31
-rw-r--r--tests/yanglint/non-interactive/data_in_format.test18
-rw-r--r--tests/yanglint/non-interactive/data_merge.test28
-rw-r--r--tests/yanglint/non-interactive/data_not_strict.test20
-rw-r--r--tests/yanglint/non-interactive/data_operational.test62
-rw-r--r--tests/yanglint/non-interactive/data_present.test25
-rw-r--r--tests/yanglint/non-interactive/data_type.test107
-rw-r--r--tests/yanglint/non-interactive/data_xpath.test42
-rw-r--r--tests/yanglint/non-interactive/debug.test25
-rw-r--r--tests/yanglint/non-interactive/disabled_searchdir.test18
-rw-r--r--tests/yanglint/non-interactive/ext_data.test29
-rw-r--r--tests/yanglint/non-interactive/extended_leafref.test13
-rw-r--r--tests/yanglint/non-interactive/format.test72
-rw-r--r--tests/yanglint/non-interactive/list.test26
-rw-r--r--tests/yanglint/non-interactive/ly.tcl8
-rw-r--r--tests/yanglint/non-interactive/make_implemented.test17
-rw-r--r--tests/yanglint/non-interactive/modcwd.yang4
-rw-r--r--tests/yanglint/non-interactive/path.test9
-rw-r--r--tests/yanglint/non-interactive/yang_library_file.test18
-rw-r--r--tests/yangre/CMakeLists.txt8
-rw-r--r--tests/yangre/all.tcl15
-rw-r--r--tests/yangre/arg.test19
-rw-r--r--tests/yangre/file.test37
-rw-r--r--tests/yangre/files/empty.txt0
-rw-r--r--tests/yangre/files/empty_str.txt2
-rw-r--r--tests/yangre/files/empty_str_err.txt2
-rw-r--r--tests/yangre/files/one_pattern.txt3
-rw-r--r--tests/yangre/files/two_patterns.txt4
-rw-r--r--tests/yangre/files/two_patterns_err.txt4
-rw-r--r--tests/yangre/files/two_patterns_invert_match.txt4
-rw-r--r--tests/yangre/files/two_patterns_invert_match_err.txt4
-rw-r--r--tests/yangre/invert_match.test28
-rw-r--r--tests/yangre/ly.tcl17
-rw-r--r--tests/yangre/pattern.test19
171 files changed, 8692 insertions, 1195 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 6f36f31..259ef34 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -45,6 +45,8 @@ if(ENABLE_TESTS)
add_subdirectory(style)
add_subdirectory(fuzz)
endif()
+ add_subdirectory(yanglint)
+ add_subdirectory(yangre)
endif()
if(ENABLE_PERF_TESTS)
add_subdirectory(perf)
diff --git a/tests/tool_i.tcl b/tests/tool_i.tcl
new file mode 100644
index 0000000..d0f3d4b
--- /dev/null
+++ b/tests/tool_i.tcl
@@ -0,0 +1,156 @@
+# @brief Common functions and variables for Tool Under Test (TUT).
+#
+# The script requires variables:
+# TUT_PATH - Assumed absolute path to the directory in which the TUT is located.
+# TUT_NAME - TUT name (without path).
+#
+# The script sets the variables:
+# TUT - The path (including the name) of the executable TUT.
+# error_prompt - Delimiter on error.
+# error_head - Header on error.
+
+package require Expect
+
+# Complete the path for Tool Under Test (TUT). For example, on Windows, TUT can be located in the Debug or Release
+# subdirectory. Note that Release build takes precedence over Debug.
+set conftypes {{} Release Debug}
+foreach i $conftypes {
+ if { [file executable "$TUT_PATH/$i/$TUT_NAME"] || [file executable "$TUT_PATH/$i/$TUT_NAME.exe"] } {
+ set TUT "$TUT_PATH/$i/$TUT_NAME"
+ break
+ }
+}
+if {![info exists TUT]} {
+ error "$TUT_NAME executable not found"
+}
+
+# prompt of error message
+set error_prompt ">>>"
+# the beginning of error message
+set error_head "$error_prompt Check-failed"
+
+# detection on eof and timeout will be on every expect command
+expect_after {
+ eof {
+ global error_head
+ error "$error_head unexpected termination"
+ } timeout {
+ global error_head
+ error "$error_head timeout"
+ }
+}
+
+# Run commands from command line
+tcltest::loadTestedCommands
+
+# namespace of internal functions
+namespace eval ly::private {}
+
+# Send command 'cmd' to the process, then check output string by 'pattern'.
+# Parameter cmd is a string of arguments.
+# Parameter pattern is a regex or an exact string to match. If is not specified, only prompt assumed afterwards.
+# It must not contain a prompt. There can be an '$' character at the end of the pattern, in which case the regex
+# matches the characters before the prompt.
+# Parameter 'opt' can contain:
+# -ex has a similar meaning to the expect command. The 'pattern' parameter is used as a simple string
+# for exact matching of the output. So 'pattern' is not a regular expression but some characters
+# must still be escaped, eg ][.
+proc ly_cmd {cmd {pattern ""} {opt ""}} {
+ global prompt
+
+ send -- "${cmd}\r"
+ expect -- "${cmd}\r\n"
+
+ if { $pattern eq "" } {
+ # command without output
+ expect ^$prompt
+ return
+ }
+
+ # definition of an expression that matches failure
+ set failure_pattern "\r\n${prompt}$"
+
+ if { $opt eq "" && [string index $pattern end] eq "$"} {
+ # check output by regular expression
+ # It was explicitly specified how the expression should end.
+ set pattern [string replace $pattern end end]
+ expect {
+ -re "${pattern}\r\n${prompt}$" {}
+ -re $failure_pattern {
+ error "unexpected output:\n$expect_out(buffer)"
+ }
+ }
+ } elseif { $opt eq "" } {
+ # check output by regular expression
+ expect {
+ -re "${pattern}.*\r\n${prompt}$" {}
+ -re $failure_pattern {
+ error "unexpected output:\n$expect_out(buffer)"
+ }
+ }
+ } elseif { $opt eq "-ex" } {
+ # check output by exact matching
+ expect {
+ -ex "${pattern}\r\n${prompt}" {}
+ -re $failure_pattern {
+ error "unexpected output:\n$expect_out(buffer)"
+ }
+ }
+ } else {
+ global error_head
+ error "$error_head unrecognized value of parameter 'opt'"
+ }
+}
+
+# Send command 'cmd' to the process, expect some header and then check output string by 'pattern'.
+# This function is useful for checking an error that appears in the form of a header.
+# Parameter header is the expected header on the output.
+# Parameter cmd is a string of arguments.
+# Parameter pattern is a regex. It must not contain a prompt.
+proc ly_cmd_header {cmd header pattern} {
+ global prompt
+
+ send -- "${cmd}\r"
+ expect -- "${cmd}\r\n"
+
+ expect {
+ -re "$header .*${pattern}.*\r\n${prompt}$" {}
+ -re "\r\n${prompt}$" {
+ error "unexpected output:\n$expect_out(buffer)"
+ }
+ }
+}
+
+# Whatever is written is sent, output is ignored and then another prompt is expected.
+# Parameter cmd is optional and any output is ignored.
+proc ly_ignore {{cmd ""}} {
+ global prompt
+
+ send "${cmd}\r"
+ expect -re "$prompt$"
+}
+
+# Send a completion request and check if the anchored regex output matches.
+proc ly_completion {input output} {
+ global prompt
+
+ send -- "${input}\t"
+ # expecting echoing input, output and 10 terminal control characters
+ expect -re "^${input}\r${prompt}${output}.*\r.*$"
+}
+
+# Send a completion request and check if the anchored regex hint options match.
+proc ly_hint {input prev_input hints} {
+ global prompt
+
+ set output {}
+ foreach i $hints {
+ # each element might have some number of spaces and CRLF around it
+ append output "${i} *(?:\\r\\n)?"
+ }
+
+ send -- "${input}\t"
+ # expecting the hints, previous input from which the hints were generated
+ # and some number of terminal control characters
+ expect -re "${output}\r${prompt}${prev_input}.*\r.*$"
+}
diff --git a/tests/tool_ni.tcl b/tests/tool_ni.tcl
new file mode 100644
index 0000000..7282d35
--- /dev/null
+++ b/tests/tool_ni.tcl
@@ -0,0 +1,141 @@
+# @brief Common functions and variables for Tool Under Test (TUT).
+#
+# The script requires variables:
+# TUT_PATH - Assumed absolute path to the directory in which the TUT is located.
+# TUT_NAME - TUT name (without path).
+#
+# The script sets the variables:
+# TUT - The path (including the name) of the executable TUT.
+# error_prompt - Delimiter on error.
+# error_head - Header on error.
+
+# Complete the path for Tool Under Test (TUT). For example, on Windows, TUT can be located in the Debug or Release
+# subdirectory. Note that Release build takes precedence over Debug.
+set conftypes {{} Release Debug}
+foreach i $conftypes {
+ if { [file executable "$TUT_PATH/$i/$TUT_NAME"] || [file executable "$TUT_PATH/$i/$TUT_NAME.exe"] } {
+ set TUT "$TUT_PATH/$i/$TUT_NAME"
+ break
+ }
+}
+if {![info exists TUT]} {
+ error "$TUT_NAME executable not found"
+}
+
+# prompt of error message
+set error_prompt ">>>"
+# the beginning of error message
+set error_head "$error_prompt Check-failed"
+
+# Run commands from command line
+tcltest::loadTestedCommands
+
+# namespace of internal functions
+namespace eval ly::private {
+ namespace export *
+}
+
+# Run the process with arguments.
+# Parameter cmd is a string with arguments.
+# Parameter wrn is a flag. Set to 1 if stderr should be ignored.
+# Returns a pair where the first is the return code and the second is the output.
+proc ly::private::ly_exec {cmd {wrn ""}} {
+ global TUT
+ try {
+ set results [exec -- $TUT {*}$cmd]
+ set status 0
+ } trap CHILDSTATUS {results options} {
+ # return code is not 0
+ set status [lindex [dict get $options -errorcode] 2]
+ } trap NONE results {
+ if { $wrn == 1 } {
+ set status 0
+ } else {
+ error "return code is 0 but something was written to stderr:\n$results\n"
+ }
+ } trap CHILDKILLED {results options} {
+ set status [lindex [dict get $options -errorcode] 2]
+ error "process was killed: $status"
+ }
+ list $status $results
+}
+
+# Internal function.
+# Check the output with pattern.
+# Parameter pattern is a regex or an exact string to match.
+# Parameter msg is the output to check.
+# Parameter 'opt' is optional. If contains '-ex', then the 'pattern' parameter is
+# used as a simple string for exact matching of the output.
+proc ly::private::output_check {pattern msg {opt ""}} {
+ if { $opt eq "" } {
+ expr {![regexp -- $pattern $msg]}
+ } elseif { $opt eq "-ex" } {
+ expr {![string equal "$pattern" $msg]}
+ } else {
+ global error_head
+ error "$error_head unrecognized value of parameter 'opt'"
+ }
+}
+
+# Execute yanglint with arguments and expect success.
+# Parameter cmd is a string of arguments.
+# Parameter pattern is a regex or an exact string to match.
+# Parameter 'opt' is optional. If contains '-ex', then the 'pattern' parameter is
+# used as a simple string for exact matching of the output.
+proc ly_cmd {cmd {pattern ""} {opt ""}} {
+ namespace import ly::private::*
+ lassign [ly_exec $cmd] rc msg
+ if { $rc != 0 } {
+ error "unexpected return code $rc:\n$msg\n"
+ }
+ if { $pattern ne "" && [output_check $pattern $msg $opt] } {
+ error "unexpected output:\n$msg\n"
+ }
+ return
+}
+
+# Execute yanglint with arguments and expect error.
+# Parameter cmd is a string of arguments.
+# Parameter pattern is a regex.
+proc ly_cmd_err {cmd pattern} {
+ namespace import ly::private::*
+ lassign [ly_exec $cmd] rc msg
+ if { $rc == 0 } {
+ error "unexpected return code $rc"
+ }
+ if { [output_check $pattern $msg] } {
+ error "unexpected output:\n$msg\n"
+ }
+ return
+}
+
+# Execute yanglint with arguments, expect warning in stderr but success.
+# Parameter cmd is a string of arguments.
+# Parameter pattern is a regex.
+proc ly_cmd_wrn {cmd pattern} {
+ namespace import ly::private::*
+ lassign [ly_exec $cmd 1] rc msg
+ if { $rc != 0 } {
+ error "unexpected return code $rc:\n$msg\n"
+ }
+ if { [output_check $pattern $msg] } {
+ error "unexpected output:\n$msg\n"
+ }
+ return
+}
+
+# Check if yanglint supports the specified option.
+# Parameter opt is a option to be found.
+# Return true if option is found otherwise false.
+proc ly_opt_exists {opt} {
+ namespace import ly::private::*
+ lassign [ly_exec "--help"] rc msg
+ if { $rc != 0 } {
+ error "unexpected return code $rc:\n$msg\n"
+ }
+ if { [output_check $opt $msg] } {
+ return false
+ } else {
+ return true
+ }
+}
diff --git a/tests/utests/basic/test_common.c b/tests/utests/basic/test_common.c
index 75235a2..46b80ab 100644
--- a/tests/utests/basic/test_common.c
+++ b/tests/utests/basic/test_common.c
@@ -1,4 +1,4 @@
-/*
+/**
* @file test_common.c
* @author: Radek Krejci <rkrejci@cesnet.cz>
* @brief unit tests for functions from common.c
diff --git a/tests/utests/basic/test_context.c b/tests/utests/basic/test_context.c
index 4c4cc3f..cfba1d3 100644
--- a/tests/utests/basic/test_context.c
+++ b/tests/utests/basic/test_context.c
@@ -1,4 +1,4 @@
-/*
+/**
* @file test_context.c
* @author: Radek Krejci <rkrejci@cesnet.cz>
* @brief unit tests for functions from context.c
@@ -298,8 +298,8 @@ test_models(void **state)
assert_int_equal(LY_EVALID, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod1));
lys_unres_glob_erase(&unres);
ly_in_free(in, 0);
- CHECK_LOG_CTX("Parsing module \"y\" failed.", NULL,
- "Name collision between module and submodule of name \"y\".", "Line number 1.");
+ CHECK_LOG_CTX("Parsing module \"y\" failed.", NULL);
+ CHECK_LOG_CTX("Name collision between module and submodule of name \"y\".", "Line number 1.");
assert_int_equal(LY_SUCCESS, ly_in_new_memory("module a {namespace urn:a;prefix a;include y;revision 2018-10-30; }", &in));
assert_int_equal(LY_SUCCESS, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod1));
@@ -308,8 +308,8 @@ test_models(void **state)
assert_int_equal(LY_EVALID, lys_parse_in(UTEST_LYCTX, in, LYS_IN_YANG, NULL, NULL, &unres.creating, &mod1));
lys_unres_glob_erase(&unres);
ly_in_free(in, 0);
- CHECK_LOG_CTX("Parsing module \"y\" failed.", NULL,
- "Name collision between module and submodule of name \"y\".", "Line number 1.");
+ CHECK_LOG_CTX("Parsing module \"y\" failed.", NULL);
+ CHECK_LOG_CTX("Name collision between module and submodule of name \"y\".", "Line number 1.");
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule y {belongs-to b {prefix b;}}");
assert_int_equal(LY_SUCCESS, ly_in_new_memory("module b {namespace urn:b;prefix b;include y;}", &in));
@@ -317,10 +317,10 @@ test_models(void **state)
lys_unres_glob_revert(UTEST_LYCTX, &unres);
lys_unres_glob_erase(&unres);
ly_in_free(in, 0);
- CHECK_LOG_CTX("Parsing module \"b\" failed.", NULL,
- "Including \"y\" submodule into \"b\" failed.", NULL,
- "Parsing submodule failed.", NULL,
- "Name collision between submodules of name \"y\".", "Line number 1.");
+ CHECK_LOG_CTX("Parsing module \"b\" failed.", NULL);
+ CHECK_LOG_CTX("Including \"y\" submodule into \"b\" failed.", NULL);
+ CHECK_LOG_CTX("Parsing submodule failed.", NULL);
+ CHECK_LOG_CTX("Name collision between submodules of name \"y\".", "Line number 1.");
/* selecting correct revision of the submodules */
ly_ctx_reset_latests(UTEST_LYCTX);
@@ -338,19 +338,6 @@ test_models(void **state)
assert_non_null(mod1->compiled);
assert_non_null(mod1->parsed);
-#if 0
- /* TODO in case we are able to remove the parsed schema, here we will test how it will handle missing import parsed schema */
-
- assert_int_equal(LY_SUCCESS, ly_in_new_memory("module z {namespace urn:z;prefix z;import w {prefix w;revision-date 2018-10-24;}}", &in));
- /* mod1->parsed is necessary to compile mod2 because of possible groupings, typedefs, ... */
- ly_ctx_set_module_imp_clb(UTEST_LYCTX, NULL, NULL);
- assert_int_equal(LY_ENOTFOUND, lys_create_module(UTEST_LYCTX, in, LYS_IN_YANG, 1, NULL, NULL, &mod2));
- /*logbuf_assert("Unable to reload \"w\" module to import it into \"z\", source data not found.");*/
- CHECK_LOG_CTX("Recompilation of module \"w\" failed.", NULL);
- assert_null(mod2);
- ly_in_free(in, 0);
-#endif
-
assert_int_equal(LY_SUCCESS, ly_in_new_memory("module z {namespace urn:z;prefix z;import w {prefix w;revision-date 2018-10-24;}}", &in));
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "module w {namespace urn:w;prefix w;revision 2018-10-24;}");
assert_int_equal(LY_SUCCESS, lys_parse(UTEST_LYCTX, in, LYS_IN_YANG, NULL, &mod2));
@@ -425,6 +412,7 @@ test_imports(void **state)
"import a {prefix a;}"
"}";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
+ ly_err_clean(UTEST_LYCTX, NULL);
}
static void
diff --git a/tests/utests/basic/test_hash_table.c b/tests/utests/basic/test_hash_table.c
index 25b595a..78950cd 100644
--- a/tests/utests/basic/test_hash_table.c
+++ b/tests/utests/basic/test_hash_table.c
@@ -1,4 +1,4 @@
-/*
+/**
* @file test_hash_table.c
* @author: Radek Krejci <rkrejci@cesnet.cz>
* @brief unit tests for functions from hash_table.c
@@ -19,8 +19,6 @@
#include "common.h"
#include "hash_table.h"
-struct ht_rec *lyht_get_rec(unsigned char *recs, uint16_t rec_size, uint32_t idx);
-
static void
test_invalid_arguments(void **state)
{
@@ -83,7 +81,7 @@ static void
test_ht_basic(void **state)
{
uint32_t i;
- struct hash_table *ht;
+ struct ly_ht *ht;
assert_non_null(ht = lyht_new(8, sizeof(int), ht_equal_clb, NULL, 0));
@@ -96,15 +94,14 @@ test_ht_basic(void **state)
assert_int_equal(LY_ENOTFOUND, lyht_remove(ht, &i, i));
CHECK_LOG("Invalid argument hash (lyht_remove_with_resize_cb()).", NULL);
- lyht_free(ht);
+ lyht_free(ht, NULL);
}
static void
test_ht_resize(void **state)
{
uint32_t i;
- struct ht_rec *rec;
- struct hash_table *ht;
+ struct ly_ht *ht;
assert_non_null(ht = lyht_new(8, sizeof(int), ht_equal_clb, NULL, 1));
assert_int_equal(8, ht->size);
@@ -120,13 +117,12 @@ test_ht_resize(void **state)
for (i = 0; i < 16; ++i) {
if ((i >= 2) && (i < 8)) {
/* inserted data on indexes 2-7 */
- rec = lyht_get_rec(ht->recs, ht->rec_size, i);
- assert_int_equal(1, rec->hits);
- assert_int_equal(i, rec->hash);
+ assert_int_not_equal(UINT32_MAX, ht->hlists[i].first);
+ assert_int_equal(LY_SUCCESS, lyht_find(ht, &i, i, NULL));
} else {
/* nothing otherwise */
- rec = lyht_get_rec(ht->recs, ht->rec_size, i);
- assert_int_equal(0, rec->hits);
+ assert_int_equal(UINT32_MAX, ht->hlists[i].first);
+ assert_int_equal(LY_ENOTFOUND, lyht_find(ht, &i, i, NULL));
}
}
@@ -153,7 +149,7 @@ test_ht_resize(void **state)
}
/* cleanup */
- lyht_free(ht);
+ lyht_free(ht, NULL);
}
static void
@@ -162,8 +158,10 @@ test_ht_collisions(void **UNUSED(state))
#define GET_REC_INT(rec) (*((uint32_t *)&(rec)->val))
uint32_t i;
- struct ht_rec *rec;
- struct hash_table *ht;
+ struct ly_ht_rec *rec;
+ struct ly_ht *ht;
+ uint32_t rec_idx;
+ int count;
assert_non_null(ht = lyht_new(8, sizeof(int), ht_equal_clb, NULL, 1));
@@ -172,66 +170,69 @@ test_ht_collisions(void **UNUSED(state))
}
/* check all records */
- for (i = 0; i < 2; ++i) {
- rec = lyht_get_rec(ht->recs, ht->rec_size, i);
- assert_int_equal(rec->hits, 0);
+ for (i = 0; i < 8; ++i) {
+ if (i == 2) {
+ assert_int_not_equal(UINT32_MAX, ht->hlists[i].first);
+ } else {
+ assert_int_equal(UINT32_MAX, ht->hlists[i].first);
+ }
}
- rec = lyht_get_rec(ht->recs, ht->rec_size, i);
- assert_int_equal(rec->hits, 4);
- assert_int_equal(GET_REC_INT(rec), i);
- ++i;
- for ( ; i < 6; ++i) {
- rec = lyht_get_rec(ht->recs, ht->rec_size, i);
- assert_int_equal(rec->hits, 1);
- assert_int_equal(GET_REC_INT(rec), i);
+ for (i = 0; i < 8; ++i) {
+ if ((i >= 2) && (i < 6)) {
+ assert_int_equal(LY_SUCCESS, lyht_find(ht, &i, 2, NULL));
+ } else {
+ assert_int_equal(LY_ENOTFOUND, lyht_find(ht, &i, 2, NULL));
+ }
}
- for ( ; i < 8; ++i) {
- rec = lyht_get_rec(ht->recs, ht->rec_size, i);
- assert_int_equal(rec->hits, 0);
+ rec_idx = ht->hlists[2].first;
+ count = 0;
+ while (rec_idx != UINT32_MAX) {
+ rec = lyht_get_rec(ht->recs, ht->rec_size, rec_idx);
+ rec_idx = rec->next;
+ assert_int_equal(rec->hash, 2);
+ count++;
}
+ assert_int_equal(count, 4);
i = 4;
assert_int_equal(lyht_remove(ht, &i, 2), 0);
rec = lyht_get_rec(ht->recs, ht->rec_size, i);
- assert_int_equal(rec->hits, -1);
i = 2;
assert_int_equal(lyht_remove(ht, &i, 2), 0);
/* check all records */
- for (i = 0; i < 2; ++i) {
- rec = lyht_get_rec(ht->recs, ht->rec_size, i);
- assert_int_equal(rec->hits, 0);
+ for (i = 0; i < 8; ++i) {
+ if (i == 2) {
+ assert_int_not_equal(UINT32_MAX, ht->hlists[i].first);
+ } else {
+ assert_int_equal(UINT32_MAX, ht->hlists[i].first);
+ }
}
- rec = lyht_get_rec(ht->recs, ht->rec_size, i);
- assert_int_equal(rec->hits, 2);
- assert_int_equal(GET_REC_INT(rec), 5);
- ++i;
- rec = lyht_get_rec(ht->recs, ht->rec_size, i);
- assert_int_equal(rec->hits, 1);
- assert_int_equal(GET_REC_INT(rec), 3);
- ++i;
- for ( ; i < 6; ++i) {
- rec = lyht_get_rec(ht->recs, ht->rec_size, i);
- assert_int_equal(rec->hits, -1);
+ for (i = 0; i < 8; ++i) {
+ if ((i == 3) || (i == 5)) {
+ assert_int_equal(LY_SUCCESS, lyht_find(ht, &i, 2, NULL));
+ } else {
+ assert_int_equal(LY_ENOTFOUND, lyht_find(ht, &i, 2, NULL));
+ }
}
- for ( ; i < 8; ++i) {
- rec = lyht_get_rec(ht->recs, ht->rec_size, i);
- assert_int_equal(rec->hits, 0);
+ rec_idx = ht->hlists[2].first;
+ count = 0;
+ while (rec_idx != UINT32_MAX) {
+ rec = lyht_get_rec(ht->recs, ht->rec_size, rec_idx);
+ rec_idx = rec->next;
+ assert_int_equal(rec->hash, 2);
+ count++;
}
+ assert_int_equal(count, 2);
- for (i = 0; i < 3; ++i) {
- assert_int_equal(lyht_find(ht, &i, 2, NULL), LY_ENOTFOUND);
- }
- assert_int_equal(lyht_find(ht, &i, 2, NULL), LY_SUCCESS);
- ++i;
- assert_int_equal(lyht_find(ht, &i, 2, NULL), LY_ENOTFOUND);
- ++i;
- assert_int_equal(lyht_find(ht, &i, 2, NULL), LY_SUCCESS);
- ++i;
- for ( ; i < 8; ++i) {
- assert_int_equal(lyht_find(ht, &i, 2, NULL), LY_ENOTFOUND);
+ for (i = 0; i < 8; ++i) {
+ if ((i == 3) || (i == 5)) {
+ assert_int_equal(lyht_find(ht, &i, 2, NULL), LY_SUCCESS);
+ } else {
+ assert_int_equal(lyht_find(ht, &i, 2, NULL), LY_ENOTFOUND);
+ }
}
i = 3;
@@ -240,20 +241,11 @@ test_ht_collisions(void **UNUSED(state))
assert_int_equal(lyht_remove(ht, &i, 2), 0);
/* check all records */
- for (i = 0; i < 2; ++i) {
- rec = lyht_get_rec(ht->recs, ht->rec_size, i);
- assert_int_equal(rec->hits, 0);
- }
- for ( ; i < 6; ++i) {
- rec = lyht_get_rec(ht->recs, ht->rec_size, i);
- assert_int_equal(rec->hits, -1);
- }
- for ( ; i < 8; ++i) {
- rec = lyht_get_rec(ht->recs, ht->rec_size, i);
- assert_int_equal(rec->hits, 0);
+ for (i = 0; i < 8; ++i) {
+ assert_int_equal(UINT32_MAX, ht->hlists[i].first);
}
- lyht_free(ht);
+ lyht_free(ht, NULL);
}
int
diff --git a/tests/utests/basic/test_inout.c b/tests/utests/basic/test_inout.c
index be27510..3f83568 100644
--- a/tests/utests/basic/test_inout.c
+++ b/tests/utests/basic/test_inout.c
@@ -84,8 +84,11 @@ test_input_mem(void **UNUSED(state))
char *str1 = "a", *str2 = "b";
assert_int_equal(LY_EINVAL, ly_in_new_memory(NULL, NULL));
+ CHECK_LOG_LASTMSG("Invalid argument str (ly_in_new_memory()).");
assert_int_equal(LY_EINVAL, ly_in_new_memory(str1, NULL));
+ CHECK_LOG_LASTMSG("Invalid argument in (ly_in_new_memory()).");
assert_null(ly_in_memory(NULL, NULL));
+ CHECK_LOG_LASTMSG("Invalid argument in (ly_in_memory()).");
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str1, &in));
assert_int_equal(LY_IN_MEMORY, ly_in_type(in));
@@ -103,12 +106,15 @@ test_input_fd(void **UNUSED(state))
struct stat statbuf;
assert_int_equal(LY_EINVAL, ly_in_new_fd(-1, NULL));
+ CHECK_LOG_LASTMSG("Invalid argument fd >= 0 (ly_in_new_fd()).");
assert_int_equal(-1, ly_in_fd(NULL, -1));
+ CHECK_LOG_LASTMSG("Invalid argument in (ly_in_fd()).");
assert_int_not_equal(-1, fd1 = open(TEST_INPUT_FILE, O_RDONLY));
assert_int_not_equal(-1, fd2 = open(TEST_INPUT_FILE, O_RDONLY));
assert_int_equal(LY_EINVAL, ly_in_new_fd(fd1, NULL));
+ CHECK_LOG_LASTMSG("Invalid argument in (ly_in_new_fd()).");
assert_int_equal(LY_SUCCESS, ly_in_new_fd(fd1, &in));
assert_int_equal(LY_IN_FD, ly_in_type(in));
diff --git a/tests/utests/basic/test_json.c b/tests/utests/basic/test_json.c
index 1896b8a..08b7719 100644
--- a/tests/utests/basic/test_json.c
+++ b/tests/utests/basic/test_json.c
@@ -1,4 +1,4 @@
-/*
+/**
* @file test_json.c
* @author: Radek Krejci <rkrejci@cesnet.cz>
* @brief unit tests for a generic JSON parser
@@ -27,39 +27,40 @@ test_general(void **state)
/* empty */
str = "";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
- lyjson_ctx_free(jsonctx);
+ assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ CHECK_LOG_CTX("Empty JSON file.", "Line number 1.");
str = " \n\t \n";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
- lyjson_ctx_free(jsonctx);
+ assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ CHECK_LOG_CTX("Empty JSON file.", "Line number 3.");
/* constant values */
str = "true";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_TRUE, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_TRUE, lyjson_ctx_status(jsonctx));
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
str = "false";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_FALSE, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_FALSE, lyjson_ctx_status(jsonctx));
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
str = "null";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NULL, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NULL, lyjson_ctx_status(jsonctx));
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
ly_in_free(in, 0);
@@ -75,8 +76,8 @@ test_number(void **state)
/* simple value */
str = "11";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("11", jsonctx->value);
assert_int_equal(2, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
@@ -85,8 +86,8 @@ test_number(void **state)
/* fraction number */
str = "37.7668";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("37.7668", jsonctx->value);
assert_int_equal(7, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
@@ -95,8 +96,8 @@ test_number(void **state)
/* negative number */
str = "-122.3959";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("-122.3959", jsonctx->value);
assert_int_equal(9, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
@@ -105,8 +106,8 @@ test_number(void **state)
/* integer, positive exponent */
str = "550E3";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("550000", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -114,8 +115,8 @@ test_number(void **state)
str = "-550E3";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("-550000", jsonctx->value);
assert_int_equal(7, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -124,8 +125,8 @@ test_number(void **state)
/* integer, negative exponent */
str = "1E-1";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.1", jsonctx->value);
assert_int_equal(3, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -133,8 +134,8 @@ test_number(void **state)
str = "15E-1";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("1.5", jsonctx->value);
assert_int_equal(3, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -142,8 +143,8 @@ test_number(void **state)
str = "-15E-1";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("-1.5", jsonctx->value);
assert_int_equal(4, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -151,8 +152,8 @@ test_number(void **state)
str = "16E-2";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.16", jsonctx->value);
assert_int_equal(4, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -160,8 +161,8 @@ test_number(void **state)
str = "-16E-2";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("-0.16", jsonctx->value);
assert_int_equal(5, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -169,8 +170,8 @@ test_number(void **state)
str = "17E-3";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.017", jsonctx->value);
assert_int_equal(5, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -178,8 +179,8 @@ test_number(void **state)
str = "-17E-3";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("-0.017", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -187,8 +188,8 @@ test_number(void **state)
str = "21000E-2";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("210", jsonctx->value);
assert_int_equal(3, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -196,8 +197,8 @@ test_number(void **state)
str = "21000E-4";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("2.1", jsonctx->value);
assert_int_equal(3, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -205,8 +206,8 @@ test_number(void **state)
str = "21000E-7";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.0021", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -215,8 +216,8 @@ test_number(void **state)
/* decimal number, positive exponent */
str = "5.087E1";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("50.87", jsonctx->value);
assert_int_equal(5, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -224,8 +225,8 @@ test_number(void **state)
str = "-5.087E1";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("-50.87", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -233,8 +234,8 @@ test_number(void **state)
str = "5.087E5";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("508700", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -242,8 +243,8 @@ test_number(void **state)
str = "59.1e+1";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("591", jsonctx->value);
assert_int_equal(3, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -251,8 +252,8 @@ test_number(void **state)
str = "0.005087E1";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.05087", jsonctx->value);
assert_int_equal(7, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -260,8 +261,8 @@ test_number(void **state)
str = "0.005087E2";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.5087", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -269,8 +270,8 @@ test_number(void **state)
str = "0.005087E6";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("5087", jsonctx->value);
assert_int_equal(4, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -278,8 +279,8 @@ test_number(void **state)
str = "0.05087E6";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("50870", jsonctx->value);
assert_int_equal(5, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -287,8 +288,8 @@ test_number(void **state)
str = "0.005087E8";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("508700", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -297,8 +298,8 @@ test_number(void **state)
/* decimal number, negative exponent */
str = "35.94e-1";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("3.594", jsonctx->value);
assert_int_equal(5, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -306,8 +307,8 @@ test_number(void **state)
str = "-35.94e-1";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("-3.594", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -315,8 +316,8 @@ test_number(void **state)
str = "35.94e-2";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.3594", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -324,8 +325,8 @@ test_number(void **state)
str = "35.94e-3";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.03594", jsonctx->value);
assert_int_equal(7, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -333,8 +334,8 @@ test_number(void **state)
str = "0.3594e-1";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.03594", jsonctx->value);
assert_int_equal(7, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -342,8 +343,8 @@ test_number(void **state)
str = "0.03594e-1";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.003594", jsonctx->value);
assert_int_equal(8, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -351,8 +352,8 @@ test_number(void **state)
str = "0.003594e-1";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.0003594", jsonctx->value);
assert_int_equal(9, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -360,8 +361,8 @@ test_number(void **state)
str = "0.3594e-2";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.003594", jsonctx->value);
assert_int_equal(8, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -369,8 +370,8 @@ test_number(void **state)
str = "0.03594e-2";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.0003594", jsonctx->value);
assert_int_equal(9, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -378,8 +379,8 @@ test_number(void **state)
str = "0.003594e-2";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.00003594", jsonctx->value);
assert_int_equal(10, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -388,8 +389,8 @@ test_number(void **state)
/* zero */
str = "0";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_true(jsonctx->value[0] == '0');
assert_int_equal(1, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
@@ -397,8 +398,8 @@ test_number(void **state)
str = "-0";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_true(jsonctx->value[0] == '-');
assert_true(jsonctx->value[1] == '0');
assert_int_equal(2, jsonctx->value_len);
@@ -407,8 +408,8 @@ test_number(void **state)
str = "94E0";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_true(jsonctx->value[0] == '9');
assert_true(jsonctx->value[1] == '4');
assert_int_equal(2, jsonctx->value_len);
@@ -417,8 +418,8 @@ test_number(void **state)
str = "0E2";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_true(jsonctx->value[0] == '0');
assert_int_equal(1, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
@@ -426,8 +427,8 @@ test_number(void **state)
str = "-0E2";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_true(jsonctx->value[0] == '-');
assert_true(jsonctx->value[1] == '0');
assert_int_equal(2, jsonctx->value_len);
@@ -436,8 +437,8 @@ test_number(void **state)
str = "5.320e+2";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("532", jsonctx->value);
assert_int_equal(3, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -445,8 +446,8 @@ test_number(void **state)
str = "5.320e-1";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_NUMBER, lyjson_ctx_status(jsonctx));
assert_string_equal("0.532", jsonctx->value);
assert_int_equal(5, jsonctx->value_len);
assert_int_equal(1, jsonctx->dynamic);
@@ -455,69 +456,64 @@ test_number(void **state)
/* various invalid inputs */
str = "-x";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
+ assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Invalid character in JSON Number value (\"x\").", "Line number 1.");
str = " -";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
+ assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Unexpected end-of-input.", "Line number 1.");
str = "--1";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
+ assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Invalid character in JSON Number value (\"-\").", "Line number 1.");
str = "+1";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
+ assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Invalid character sequence \"+1\", expected a JSON value.", "Line number 1.");
str = " 1.x ";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
+ assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Invalid character in JSON Number value (\"x\").", "Line number 1.");
str = "1.";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
+ assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Unexpected end-of-input.", "Line number 1.");
str = " 1eo ";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
+ assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Invalid character in JSON Number value (\"o\").", "Line number 1.");
str = "1e";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
+ assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Unexpected end-of-input.", "Line number 1.");
str = "1E1000";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
+ assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Number encoded as a string exceeded the LY_NUMBER_MAXLEN limit.", "Line number 1.");
str = "1e9999999999999999999";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
+ assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Exponent out-of-bounds in a JSON Number value (1e9999999999999999999).", "Line number 1.");
str = "1.1e66000";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
+ assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Exponent out-of-bounds in a JSON Number value (1.1e66000).", "Line number 1.");
str = "1.1e-66000";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
+ assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Exponent out-of-bounds in a JSON Number value (1.1e-66000).", "Line number 1.");
- str = "-2.1e0.";
- assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- CHECK_LOG_CTX("Unexpected character \".\" after JSON number.", "Line number 1.");
-
ly_in_free(in, 0);
}
@@ -532,68 +528,12 @@ test_string(void **state)
str = "";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
-#if 0
- /* simple string */
- str = "\"hello\"";
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_STRING, lyjson_ctx_status(jsonctx, 0));
- assert_ptr_equal(&str[1], jsonctx->value);
- assert_int_equal(5, jsonctx->value_len);
- assert_int_equal(0, jsonctx->dynamic);
- lyjson_ctx_free(jsonctx);
-
- /* 4-byte utf8 character */
- str = "\"\\t𠜎\"";
- assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_STRING, lyjson_ctx_status(jsonctx, 0));
- assert_string_equal("\t𠜎", jsonctx->value);
- assert_int_equal(5, jsonctx->value_len);
- assert_int_equal(1, jsonctx->dynamic);
- lyjson_ctx_free(jsonctx);
-
- /* valid escape sequences - note that here it mixes valid JSON string characters (RFC 7159, sec. 7) and
- * valid characters in YANG string type (RFC 7950, sec. 9.4). Since the latter is a subset of JSON string,
- * the YANG string type's restrictions apply to the JSON escape sequences */
- str = "\"\\\" \\\\ \\r \\/ \\n \\t \\u20ac\"";
- assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_STRING, lyjson_ctx_status(jsonctx, 0));
- assert_string_equal("\" \\ \r / \n \t €", jsonctx->value);
- assert_int_equal(15, jsonctx->value_len);
- assert_int_equal(1, jsonctx->dynamic);
- lyjson_ctx_free(jsonctx);
-
- /* backspace and form feed are valid JSON escape sequences, but the control characters they represents are not allowed values for YANG string type */
- str = "\"\\b\"";
- assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- CHECK_LOG_CTX("Invalid character reference \"\\b\" (0x00000008).", "Line number 1.");
-
- str = "\"\\f\"";
- assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- CHECK_LOG_CTX("Invalid character reference \"\\f\" (0x0000000c).", "Line number 1.");
-#endif
-
/* unterminated string */
str = "\"unterminated string";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
+ assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
CHECK_LOG_CTX("Missing quotation-mark at the end of a JSON string.", "Line number 1.");
-#if 0
- /* invalid escape sequence */
- str = "\"char \\x \"";
- assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- CHECK_LOG_CTX("Invalid character escape sequence \\x.", "Line number 1.");
-
- /* new line is allowed only as escaped character in JSON */
- str = "\"\n\"";
- assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- CHECK_LOG_CTX("Invalid character in JSON string \"\n\" (0x0000000a).", "Line number 1.");
-#endif
+ CHECK_LOG_CTX("Unexpected end-of-input.", "Line number 1.");
ly_in_free(in, 0);
}
@@ -608,95 +548,122 @@ test_object(void **state)
/* empty */
str = " { } ";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_OBJECT_EMPTY, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx));
+
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
+ assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx));
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
/* simple value */
str = "{\"name\" : \"Radek\"}";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx, 0));
+
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx));
+
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
+ assert_int_equal(LYJSON_OBJECT_NAME, lyjson_ctx_status(jsonctx));
assert_ptr_equal(&str[2], jsonctx->value);
assert_int_equal(4, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
- assert_string_equal("\"Radek\"}", jsonctx->in->current);
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_STRING, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_STRING, lyjson_ctx_status(jsonctx));
assert_string_equal("Radek\"}", jsonctx->value);
assert_int_equal(5, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
- assert_string_equal("}", jsonctx->in->current);
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx));
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
/* two values */
str = "{\"smart\" : true,\"handsom\":false}";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx));
+
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
+ assert_int_equal(LYJSON_OBJECT_NAME, lyjson_ctx_status(jsonctx));
assert_string_equal("smart\" : true,\"handsom\":false}", jsonctx->value);
assert_int_equal(5, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
- assert_string_equal("true,\"handsom\":false}", jsonctx->in->current);
+
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
+ assert_int_equal(LYJSON_TRUE, lyjson_ctx_status(jsonctx));
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_TRUE, lyjson_ctx_status(jsonctx, 0));
- assert_string_equal(",\"handsom\":false}", jsonctx->in->current);
+ assert_int_equal(LYJSON_OBJECT_NEXT, lyjson_ctx_status(jsonctx));
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_OBJECT_NAME, lyjson_ctx_status(jsonctx));
assert_string_equal("handsom\":false}", jsonctx->value);
assert_int_equal(7, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
- assert_string_equal("false}", jsonctx->in->current);
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_FALSE, lyjson_ctx_status(jsonctx, 0));
- assert_string_equal("}", jsonctx->in->current);
+ assert_int_equal(LYJSON_FALSE, lyjson_ctx_status(jsonctx));
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx));
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
/* inherited objects */
str = "{\"person\" : {\"name\":\"Radek\"}}";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx));
+
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
+ assert_int_equal(LYJSON_OBJECT_NAME, lyjson_ctx_status(jsonctx));
assert_string_equal("person\" : {\"name\":\"Radek\"}}", jsonctx->value);
assert_int_equal(6, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
- assert_string_equal("{\"name\":\"Radek\"}}", jsonctx->in->current);
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx));
+
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
+ assert_int_equal(LYJSON_OBJECT_NAME, lyjson_ctx_status(jsonctx));
assert_string_equal("name\":\"Radek\"}}", jsonctx->value);
assert_int_equal(4, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
- assert_string_equal("\"Radek\"}}", jsonctx->in->current);
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_STRING, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_STRING, lyjson_ctx_status(jsonctx));
assert_string_equal("Radek\"}}", jsonctx->value);
assert_int_equal(5, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
- assert_string_equal("}}", jsonctx->in->current);
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx, 0));
- assert_string_equal("}", jsonctx->in->current);
+ assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx));
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx));
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
- /* new line is allowed only as escaped character in JSON */
+ /* unquoted string */
str = "{ unquoted : \"data\"}";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_EVALID, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- CHECK_LOG_CTX("Invalid character sequence \"unquoted : \"data\"}\", expected a JSON object's member.", "Line number 1.");
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx));
+
+ assert_int_equal(LY_EVALID, lyjson_ctx_next(jsonctx, NULL));
+ CHECK_LOG_CTX("Invalid character sequence \"unquoted : \"data\"}\", expected a JSON object name.", "Line number 1.");
+ lyjson_ctx_free(jsonctx);
ly_in_free(in, 0);
}
@@ -711,67 +678,79 @@ test_array(void **state)
/* empty */
str = " [ ] ";
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_ARRAY_EMPTY, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_ARRAY, lyjson_ctx_status(jsonctx));
+
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
+ assert_int_equal(LYJSON_ARRAY_CLOSED, lyjson_ctx_status(jsonctx));
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
/* simple value */
str = "[ null]";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_ARRAY, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_ARRAY, lyjson_ctx_status(jsonctx));
assert_null(jsonctx->value);
assert_int_equal(0, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
- assert_string_equal("null]", jsonctx->in->current);
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_NULL, lyjson_ctx_status(jsonctx, 0));
- assert_string_equal("]", jsonctx->in->current);
+ assert_int_equal(LYJSON_NULL, lyjson_ctx_status(jsonctx));
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_ARRAY_CLOSED, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_ARRAY_CLOSED, lyjson_ctx_status(jsonctx));
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
/* two values */
str = "[{\"a\":null},\"x\"]";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
- assert_int_equal(LYJSON_ARRAY, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
+ assert_int_equal(LYJSON_ARRAY, lyjson_ctx_status(jsonctx));
assert_null(jsonctx->value);
assert_int_equal(0, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
- assert_string_equal("{\"a\":null},\"x\"]", jsonctx->in->current);
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_OBJECT, lyjson_ctx_status(jsonctx));
+
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
+ assert_int_equal(LYJSON_OBJECT_NAME, lyjson_ctx_status(jsonctx));
assert_string_equal("a\":null},\"x\"]", jsonctx->value);
assert_int_equal(1, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
- assert_string_equal("null},\"x\"]", jsonctx->in->current);
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_NULL, lyjson_ctx_status(jsonctx, 0));
- assert_string_equal("},\"x\"]", jsonctx->in->current);
+ assert_int_equal(LYJSON_NULL, lyjson_ctx_status(jsonctx));
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx, 0));
- assert_string_equal(",\"x\"]", jsonctx->in->current);
+ assert_int_equal(LYJSON_OBJECT_CLOSED, lyjson_ctx_status(jsonctx));
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_STRING, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_ARRAY_NEXT, lyjson_ctx_status(jsonctx));
+
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
+ assert_int_equal(LYJSON_STRING, lyjson_ctx_status(jsonctx));
assert_string_equal("x\"]", jsonctx->value);
assert_int_equal(1, jsonctx->value_len);
assert_int_equal(0, jsonctx->dynamic);
- assert_string_equal("]", jsonctx->in->current);
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_ARRAY_CLOSED, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_ARRAY_CLOSED, lyjson_ctx_status(jsonctx));
+
assert_int_equal(LY_SUCCESS, lyjson_ctx_next(jsonctx, NULL));
- assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx, 0));
+ assert_int_equal(LYJSON_END, lyjson_ctx_status(jsonctx));
lyjson_ctx_free(jsonctx);
/* new line is allowed only as escaped character in JSON */
str = "[ , null]";
assert_non_null(ly_in_memory(in, str));
- assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, 0, &jsonctx));
+ assert_int_equal(LY_SUCCESS, lyjson_ctx_new(UTEST_LYCTX, in, &jsonctx));
assert_int_equal(LY_EVALID, lyjson_ctx_next(jsonctx, NULL));
CHECK_LOG_CTX("Invalid character sequence \", null]\", expected a JSON value.", "Line number 1.");
lyjson_ctx_free(jsonctx);
diff --git a/tests/utests/basic/test_plugins.c b/tests/utests/basic/test_plugins.c
index 7f3fe40..de13c0b 100644
--- a/tests/utests/basic/test_plugins.c
+++ b/tests/utests/basic/test_plugins.c
@@ -1,4 +1,4 @@
-/*
+/**
* @file test_plugins.c
* @author: Radek Krejci <rkrejci@cesnet.cz>
* @brief unit tests for functions from set.c
diff --git a/tests/utests/basic/test_set.c b/tests/utests/basic/test_set.c
index af39afa..9485927 100644
--- a/tests/utests/basic/test_set.c
+++ b/tests/utests/basic/test_set.c
@@ -1,4 +1,4 @@
-/*
+/**
* @file test_set.c
* @author: Radek Krejci <rkrejci@cesnet.cz>
* @brief unit tests for functions from set.c
diff --git a/tests/utests/basic/test_xml.c b/tests/utests/basic/test_xml.c
index 668de4b..071846a 100644
--- a/tests/utests/basic/test_xml.c
+++ b/tests/utests/basic/test_xml.c
@@ -1,4 +1,4 @@
-/*
+/**
* @file test_xml.c
* @author: Radek Krejci <rkrejci@cesnet.cz>
* @brief unit tests for functions from xml.c
diff --git a/tests/utests/basic/test_xpath.c b/tests/utests/basic/test_xpath.c
index b388dc3..754abf2 100644
--- a/tests/utests/basic/test_xpath.c
+++ b/tests/utests/basic/test_xpath.c
@@ -88,6 +88,19 @@ const char *schema_a =
" type string;\n"
" }\n"
" }\n"
+ "\n"
+ " rpc r {\n"
+ " input {\n"
+ " leaf l {\n"
+ " type string;\n"
+ " }\n"
+ " }\n"
+ " output {\n"
+ " leaf l {\n"
+ " type string;\n"
+ " }\n"
+ " }\n"
+ " }\n"
"}";
static int
@@ -254,9 +267,11 @@ test_invalid(void **state)
assert_int_equal(LY_EVALID, lyd_find_xpath(tree, "/a:foo2[.=]", &set));
assert_null(set);
+ CHECK_LOG_CTX("Unexpected XPath token \"]\" (\"]\").", NULL);
assert_int_equal(LY_EVALID, lyd_find_xpath(tree, "/a:", &set));
assert_null(set);
+ CHECK_LOG_CTX("Invalid character 'a'[2] of expression '/a:'.", NULL);
lyd_free_all(tree);
}
@@ -381,6 +396,31 @@ test_hash(void **state)
}
static void
+test_rpc(void **state)
+{
+ const char *data =
+ "<r xmlns=\"urn:tests:a\">\n"
+ " <l>val</l>\n"
+ "</r>";
+ struct ly_in *in;
+ struct lyd_node *tree;
+ struct ly_set *set;
+
+ assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
+ assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_REPLY_YANG, &tree, NULL));
+ ly_in_free(in, 0);
+ assert_non_null(tree);
+
+ /* name collision input/output, hashes are not used */
+ assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:r/l", &set));
+ assert_int_equal(1, set->count);
+
+ ly_set_free(set, NULL);
+
+ lyd_free_all(tree);
+}
+
+static void
test_toplevel(void **state)
{
const char *schema_b =
@@ -479,7 +519,7 @@ test_atomize(void **state)
/* some random paths just making sure the API function works */
assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/a:*", 0, &set));
- assert_int_equal(6, set->count);
+ assert_int_equal(7, set->count);
ly_set_free(set, NULL);
/* all nodes from all modules (including internal, which can change easily, so check just the test modules) */
@@ -496,7 +536,7 @@ test_atomize(void **state)
ly_set_free(set, NULL);
assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/*", 0, &set));
- assert_int_equal(13, set->count);
+ assert_int_equal(14, set->count);
ly_set_free(set, NULL);
/*
@@ -530,7 +570,7 @@ test_atomize(void **state)
/* descendant-or-self */
assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/a:*/descendant-or-self::c", 0, &set));
- assert_int_equal(7, set->count);
+ assert_int_equal(8, set->count);
ly_set_free(set, NULL);
/* following */
@@ -545,11 +585,11 @@ test_atomize(void **state)
/* parent */
assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/child::a:*/c/parent::l1", 0, &set));
- assert_int_equal(7, set->count);
+ assert_int_equal(8, set->count);
ly_set_free(set, NULL);
assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/child::a:c//..", 0, &set));
- assert_int_equal(8, set->count);
+ assert_int_equal(11, set->count);
ly_set_free(set, NULL);
/* preceding */
@@ -898,6 +938,7 @@ test_variables(void **state)
LOCAL_SETUP(data, tree);
assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "\"mstr\""));
assert_int_equal(LY_ENOTFOUND, lyd_find_xpath2(tree, "/foo[text() = $var55]", vars, &set));
+ CHECK_LOG_CTX("Variable \"var55\" not defined.", NULL);
LOCAL_TEARDOWN(set, tree, vars);
/* Syntax error in value. */
@@ -906,6 +947,7 @@ test_variables(void **state)
LOCAL_SETUP(data, tree);
assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "\""));
assert_int_equal(LY_EVALID, lyd_find_xpath2(tree, "/foo[$var]", vars, &set));
+ CHECK_LOG_CTX("Unterminated string delimited with \" (\").", "Data location \"/a:foo\".");
LOCAL_TEARDOWN(set, tree, vars);
/* Prefix is not supported. */
@@ -914,7 +956,7 @@ test_variables(void **state)
LOCAL_SETUP(data, tree);
assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "\""));
assert_int_equal(LY_EVALID, lyd_find_xpath2(tree, "/foo[$pref:var]", vars, &set));
- assert_string_equal("Variable with prefix is not supported.", _UC->err_msg);
+ CHECK_LOG_CTX("Variable with prefix is not supported.", NULL);
LOCAL_TEARDOWN(set, tree, vars);
#undef LOCAL_SETUP
@@ -1050,6 +1092,154 @@ test_axes(void **state)
lyd_free_all(tree);
}
+static void
+test_trim(void **state)
+{
+ const char *data;
+ char *str1;
+ struct lyd_node *tree;
+
+ data =
+ "<l1 xmlns=\"urn:tests:a\">"
+ " <a>a1</a>"
+ " <b>b1</b>"
+ " <c>c1</c>"
+ "</l1>"
+ "<l1 xmlns=\"urn:tests:a\">"
+ " <a>a2</a>"
+ " <b>b2</b>"
+ "</l1>"
+ "<l1 xmlns=\"urn:tests:a\">"
+ " <a>a3</a>"
+ " <b>b3</b>"
+ "</l1>"
+ "<l1 xmlns=\"urn:tests:a\">"
+ " <a>a4</a>"
+ " <b>b4</b>"
+ " <c>c4</c>"
+ "</l1>"
+ "<l1 xmlns=\"urn:tests:a\">"
+ " <a>a5</a>"
+ " <b>b5</b>"
+ " <c>c5</c>"
+ "</l1>"
+ "<foo2 xmlns=\"urn:tests:a\">50</foo2>"
+ "<c xmlns=\"urn:tests:a\">"
+ " <x>key2</x>"
+ " <ll>"
+ " <a>key1</a>"
+ " <ll>"
+ " <a>key11</a>"
+ " <b>val11</b>"
+ " </ll>"
+ " <ll>"
+ " <a>key12</a>"
+ " <b>val12</b>"
+ " </ll>"
+ " <ll>"
+ " <a>key13</a>"
+ " <b>val13</b>"
+ " </ll>"
+ " </ll>"
+ " <ll>"
+ " <a>key2</a>"
+ " <ll>"
+ " <a>key21</a>"
+ " <b>val21</b>"
+ " </ll>"
+ " <ll>"
+ " <a>key22</a>"
+ " <b>val22</b>"
+ " </ll>"
+ " </ll>"
+ " <ll>"
+ " <a>key3</a>"
+ " <ll>"
+ " <a>key31</a>"
+ " <b>val31</b>"
+ " </ll>"
+ " <ll>"
+ " <a>key32</a>"
+ " <b>val32</b>"
+ " </ll>"
+ " </ll>"
+ "</c>";
+
+ /* trim #1 */
+ assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
+ assert_non_null(tree);
+
+ assert_int_equal(LY_SUCCESS, lyd_trim_xpath(&tree, "/a:c/ll/ll[a='key11']", NULL));
+ lyd_print_mem(&str1, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS);
+ assert_string_equal(str1,
+ "<c xmlns=\"urn:tests:a\">\n"
+ " <ll>\n"
+ " <a>key1</a>\n"
+ " <ll>\n"
+ " <a>key11</a>\n"
+ " <b>val11</b>\n"
+ " </ll>\n"
+ " </ll>\n"
+ "</c>\n");
+
+ free(str1);
+ lyd_free_all(tree);
+
+ /* trim #2 */
+ assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
+ assert_non_null(tree);
+
+ assert_int_equal(LY_SUCCESS, lyd_trim_xpath(&tree, "/a:c/ll/ll[contains(.,'2')]", NULL));
+ lyd_print_mem(&str1, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS);
+ assert_string_equal(str1,
+ "<c xmlns=\"urn:tests:a\">\n"
+ " <ll>\n"
+ " <a>key1</a>\n"
+ " <ll>\n"
+ " <a>key12</a>\n"
+ " <b>val12</b>\n"
+ " </ll>\n"
+ " </ll>\n"
+ " <ll>\n"
+ " <a>key2</a>\n"
+ " <ll>\n"
+ " <a>key21</a>\n"
+ " <b>val21</b>\n"
+ " </ll>\n"
+ " <ll>\n"
+ " <a>key22</a>\n"
+ " <b>val22</b>\n"
+ " </ll>\n"
+ " </ll>\n"
+ " <ll>\n"
+ " <a>key3</a>\n"
+ " <ll>\n"
+ " <a>key32</a>\n"
+ " <b>val32</b>\n"
+ " </ll>\n"
+ " </ll>\n"
+ "</c>\n");
+
+ free(str1);
+ lyd_free_all(tree);
+
+ /* trim #3 */
+ assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
+ assert_non_null(tree);
+
+ assert_int_equal(LY_SUCCESS, lyd_trim_xpath(&tree, "/l1[4]//.", NULL));
+ lyd_print_mem(&str1, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS);
+ assert_string_equal(str1,
+ "<l1 xmlns=\"urn:tests:a\">\n"
+ " <a>a4</a>\n"
+ " <b>b4</b>\n"
+ " <c>c4</c>\n"
+ "</l1>\n");
+
+ free(str1);
+ lyd_free_all(tree);
+}
+
int
main(void)
{
@@ -1058,6 +1248,7 @@ main(void)
UTEST(test_union, setup),
UTEST(test_invalid, setup),
UTEST(test_hash, setup),
+ UTEST(test_rpc, setup),
UTEST(test_toplevel, setup),
UTEST(test_atomize, setup),
UTEST(test_canonize, setup),
@@ -1065,6 +1256,7 @@ main(void)
UTEST(test_augment, setup),
UTEST(test_variables, setup),
UTEST(test_axes, setup),
+ UTEST(test_trim, setup),
};
return cmocka_run_group_tests(tests, NULL, NULL);
diff --git a/tests/utests/data/test_diff.c b/tests/utests/data/test_diff.c
index 1b7592a..4400b5d 100644
--- a/tests/utests/data/test_diff.c
+++ b/tests/utests/data/test_diff.c
@@ -4,7 +4,7 @@
* @author Michal Vasko <mvasko@cesnet.cz>
* @brief tests for lyd_diff()
*
- * Copyright (c) 2020 CESNET, z.s.p.o.
+ * Copyright (c) 2020 - 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.
@@ -17,15 +17,15 @@
#include "libyang.h"
-#define CHECK_PARSE_LYD(INPUT, MODEL) \
- CHECK_PARSE_LYD_PARAM(INPUT, LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, MODEL)
+#define CHECK_PARSE_LYD(INPUT, OUTPUT) \
+ CHECK_PARSE_LYD_PARAM(INPUT, LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, OUTPUT)
-#define CHECK_LYD_STRING(IN_MODEL, TEXT) \
- CHECK_LYD_STRING_PARAM(IN_MODEL, TEXT, LYD_XML, LYD_PRINT_WITHSIBLINGS)
+#define CHECK_LYD_STRING(INPUT, TEXT) \
+ CHECK_LYD_STRING_PARAM(INPUT, TEXT, LYD_XML, LYD_PRINT_WITHSIBLINGS)
-#define CHECK_PARSE_LYD_DIFF(INPUT_1, INPUT_2, OUT_MODEL) \
- assert_int_equal(LY_SUCCESS, lyd_diff_siblings(INPUT_1, INPUT_2, 0, &OUT_MODEL));\
- assert_non_null(OUT_MODEL)
+#define CHECK_PARSE_LYD_DIFF(INPUT_1, INPUT_2, OUT_DIFF) \
+ assert_int_equal(LY_SUCCESS, lyd_diff_siblings(INPUT_1, INPUT_2, 0, &OUT_DIFF));\
+ assert_non_null(OUT_DIFF)
#define TEST_DIFF_3(XML1, XML2, XML3, DIFF1, DIFF2, MERGE) \
{ \
@@ -117,6 +117,12 @@ const char *schema1 =
" leaf l2 {\n"
" type int32;\n"
" }\n"
+ ""
+ " container cont {\n"
+ " leaf l3 {\n"
+ " type string;\n"
+ " }\n"
+ " }\n"
" }\n"
""
" leaf-list dllist {\n"
@@ -312,6 +318,8 @@ test_invalid(void **state)
struct lyd_node *diff = NULL;
assert_int_equal(lyd_diff_siblings(model_1, lyd_child(model_1), 0, &diff), LY_EINVAL);
+ CHECK_LOG_CTX("Invalid arguments - cannot create diff for unrelated data (lyd_diff()).", NULL);
+
assert_int_equal(lyd_diff_siblings(NULL, NULL, 0, NULL), LY_EINVAL);
lyd_free_all(model_1);
@@ -637,6 +645,126 @@ test_list(void **state)
}
static void
+test_nested_list(void **state)
+{
+ struct lyd_node *data1, *data2, *diff;
+ const char *xml1, *xml2;
+
+ (void) state;
+
+ xml1 =
+ "<df xmlns=\"urn:libyang:tests:defaults\">"
+ " <list>"
+ " <name>n1</name>"
+ " <value>25</value>"
+ " <list2>"
+ " <name2>n22</name2>"
+ " <value2>26</value2>"
+ " </list2>"
+ " </list>"
+ " <list>"
+ " <name>n2</name>"
+ " <value>25</value>"
+ " <list2>"
+ " <name2>n22</name2>"
+ " <value2>26</value2>"
+ " </list2>"
+ " </list>"
+ " <list>"
+ " <name>n3</name>"
+ " <value>25</value>"
+ " <list2>"
+ " <name2>n22</name2>"
+ " <value2>26</value2>"
+ " </list2>"
+ " </list>"
+ " <list>"
+ " <name>n4</name>"
+ " <value>25</value>"
+ " <list2>"
+ " <name2>n22</name2>"
+ " <value2>26</value2>"
+ " </list2>"
+ " </list>"
+ " <list>"
+ " <name>n0</name>"
+ " <value>26</value>"
+ " <list2>"
+ " <name2>n22</name2>"
+ " <value2>26</value2>"
+ " </list2>"
+ " <list2>"
+ " <name2>n23</name2>"
+ " <value2>26</value2>"
+ " </list2>"
+ " </list>"
+ "</df>";
+ xml2 =
+ "<df xmlns=\"urn:libyang:tests:defaults\">"
+ " <list>"
+ " <name>n0</name>"
+ " <value>30</value>"
+ " <list2>"
+ " <name2>n23</name2>"
+ " <value2>26</value2>"
+ " </list2>"
+ " </list>"
+ "</df>";
+
+ CHECK_PARSE_LYD(xml1, data1);
+ CHECK_PARSE_LYD(xml2, data2);
+ CHECK_PARSE_LYD_DIFF(data1, data2, diff);
+
+ CHECK_LYD_STRING(diff,
+ "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
+ " <list yang:operation=\"delete\">\n"
+ " <name>n1</name>\n"
+ " <value>25</value>\n"
+ " <list2>\n"
+ " <name2>n22</name2>\n"
+ " <value2>26</value2>\n"
+ " </list2>\n"
+ " </list>\n"
+ " <list yang:operation=\"delete\">\n"
+ " <name>n2</name>\n"
+ " <value>25</value>\n"
+ " <list2>\n"
+ " <name2>n22</name2>\n"
+ " <value2>26</value2>\n"
+ " </list2>\n"
+ " </list>\n"
+ " <list yang:operation=\"delete\">\n"
+ " <name>n3</name>\n"
+ " <value>25</value>\n"
+ " <list2>\n"
+ " <name2>n22</name2>\n"
+ " <value2>26</value2>\n"
+ " </list2>\n"
+ " </list>\n"
+ " <list yang:operation=\"delete\">\n"
+ " <name>n4</name>\n"
+ " <value>25</value>\n"
+ " <list2>\n"
+ " <name2>n22</name2>\n"
+ " <value2>26</value2>\n"
+ " </list2>\n"
+ " </list>\n"
+ " <list yang:operation=\"none\">\n"
+ " <name>n0</name>\n"
+ " <value yang:operation=\"replace\" yang:orig-default=\"false\" yang:orig-value=\"26\">30</value>\n"
+ " <list2 yang:operation=\"delete\">\n"
+ " <name2>n22</name2>\n"
+ " <value2>26</value2>\n"
+ " </list2>\n"
+ " </list>\n"
+ "</df>\n");
+
+ lyd_free_all(data1);
+ lyd_free_all(data2);
+ lyd_free_all(diff);
+}
+
+static void
test_userord_llist(void **state)
{
(void) state;
@@ -940,6 +1068,118 @@ test_userord_list2(void **state)
}
static void
+test_userord_list3(void **state)
+{
+ (void) state;
+ const char *xml1 =
+ "<df xmlns=\"urn:libyang:tests:defaults\">\n"
+ " <ul>\n"
+ " <l1>a</l1>\n"
+ " <l2>1</l2>\n"
+ " </ul>\n"
+ " <ul>\n"
+ " <l1>b</l1>\n"
+ " <l2>2</l2>\n"
+ " </ul>\n"
+ " <ul>\n"
+ " <l1>c</l1>\n"
+ " <cont>\n"
+ " <l3>val1</l3>\n"
+ " </cont>\n"
+ " </ul>\n"
+ " <ul>\n"
+ " <l1>d</l1>\n"
+ " <l2>4</l2>\n"
+ " </ul>\n"
+ "</df>\n";
+ const char *xml2 =
+ "<df xmlns=\"urn:libyang:tests:defaults\">\n"
+ " <ul>\n"
+ " <l1>c</l1>\n"
+ " <l2>3</l2>\n"
+ " <cont>\n"
+ " <l3>val2</l3>\n"
+ " </cont>\n"
+ " </ul>\n"
+ " <ul>\n"
+ " <l1>a</l1>\n"
+ " <l2>1</l2>\n"
+ " </ul>\n"
+ " <ul>\n"
+ " <l1>d</l1>\n"
+ " <l2>44</l2>\n"
+ " </ul>\n"
+ " <ul>\n"
+ " <l1>b</l1>\n"
+ " <l2>2</l2>\n"
+ " </ul>\n"
+ "</df>\n";
+ const char *xml3 =
+ "<df xmlns=\"urn:libyang:tests:defaults\">\n"
+ " <ul>\n"
+ " <l1>a</l1>\n"
+ " </ul>\n"
+ " <ul>\n"
+ " <l1>c</l1>\n"
+ " <l2>3</l2>\n"
+ " <cont>\n"
+ " <l3>val2</l3>\n"
+ " </cont>\n"
+ " </ul>\n"
+ " <ul>\n"
+ " <l1>d</l1>\n"
+ " <l2>44</l2>\n"
+ " </ul>\n"
+ " <ul>\n"
+ " <l1>b</l1>\n"
+ " <l2>2</l2>\n"
+ " </ul>\n"
+ "</df>\n";
+
+ const char *out_diff_1 =
+ "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
+ " <ul yang:operation=\"replace\" yang:key=\"\" yang:orig-key=\"[l1='b']\">\n"
+ " <l1>c</l1>\n"
+ " <l2 yang:operation=\"create\">3</l2>\n"
+ " <cont yang:operation=\"none\">\n"
+ " <l3 yang:operation=\"replace\" yang:orig-default=\"false\" yang:orig-value=\"val1\">val2</l3>\n"
+ " </cont>\n"
+ " </ul>\n"
+ " <ul yang:operation=\"replace\" yang:key=\"[l1='a']\" yang:orig-key=\"[l1='b']\">\n"
+ " <l1>d</l1>\n"
+ " <l2 yang:operation=\"replace\" yang:orig-default=\"false\" yang:orig-value=\"4\">44</l2>\n"
+ " </ul>\n"
+ "</df>\n";
+ const char *out_diff_2 =
+ "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
+ " <ul yang:operation=\"replace\" yang:key=\"\" yang:orig-key=\"[l1='c']\">\n"
+ " <l1>a</l1>\n"
+ " <l2 yang:operation=\"delete\">1</l2>\n"
+ " </ul>\n"
+ "</df>\n";
+ const char *out_merge =
+ "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
+ " <ul yang:operation=\"replace\" yang:key=\"\" yang:orig-key=\"[l1='b']\">\n"
+ " <l1>c</l1>\n"
+ " <l2 yang:operation=\"create\">3</l2>\n"
+ " <cont yang:operation=\"none\">\n"
+ " <l3 yang:operation=\"replace\" yang:orig-default=\"false\" yang:orig-value=\"val1\">val2</l3>\n"
+ " </cont>\n"
+ " </ul>\n"
+ " <ul yang:operation=\"replace\" yang:key=\"[l1='a']\" yang:orig-key=\"[l1='b']\">\n"
+ " <l1>d</l1>\n"
+ " <l2 yang:operation=\"replace\" yang:orig-default=\"false\" yang:orig-value=\"4\">44</l2>\n"
+ " </ul>\n"
+ " <ul yang:key=\"\" yang:orig-key=\"[l1='c']\" yang:operation=\"replace\">\n"
+ " <l1>a</l1>\n"
+ " <l2 yang:operation=\"delete\">1</l2>\n"
+ " </ul>\n"
+ "</df>\n";
+
+ TEST_DIFF_3(xml1, xml2, xml3, out_diff_1, out_diff_2, out_merge);
+}
+
+static void
test_keyless_list(void **state)
{
(void) state;
@@ -1207,11 +1447,13 @@ main(void)
UTEST(test_delete_merge, setup),
UTEST(test_leaf, setup),
UTEST(test_list, setup),
+ UTEST(test_nested_list, setup),
UTEST(test_userord_llist, setup),
UTEST(test_userord_llist2, setup),
UTEST(test_userord_mix, setup),
UTEST(test_userord_list, setup),
UTEST(test_userord_list2, setup),
+ UTEST(test_userord_list3, setup),
UTEST(test_keyless_list, setup),
UTEST(test_state_llist, setup),
UTEST(test_wd, setup),
diff --git a/tests/utests/data/test_new.c b/tests/utests/data/test_new.c
index 7642960..5cee903 100644
--- a/tests/utests/data/test_new.c
+++ b/tests/utests/data/test_new.c
@@ -55,6 +55,7 @@ const char *schema_a = "module a {\n"
" anydata any {\n"
" config false;\n"
" }\n"
+ " anyxml anyx;\n"
" leaf-list ll2 {\n"
" config false;\n"
" type string;\n"
@@ -128,6 +129,16 @@ test_top_level(void **state)
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_bin(NULL, mod, "l1", (const void **)key_vals, val_lens, 0, &node), LY_SUCCESS);
+ lyd_free_tree(node);
+
/* 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']\".", "Schema location \"/a:foo\".");
@@ -290,6 +301,7 @@ test_path(void **state)
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.", "Data location \"/a:c2/l3[1]\".");
ret = lyd_new_path2(root, NULL, "/a:c2/l3[2]/x", "val2", 0, 0, 0, NULL, &node);
assert_int_equal(ret, LY_SUCCESS);
@@ -348,6 +360,7 @@ test_path(void **state)
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.", "Data location \"/a:ll2[1]\".");
ret = lyd_new_path2(root, NULL, "/a:ll2[2]", "val2", 0, 0, 0, NULL, &node);
assert_int_equal(ret, LY_SUCCESS);
@@ -362,6 +375,7 @@ test_path(void **state)
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);
lyd_print_mem(&str, root, LYD_XML, LYD_PRINT_WITHSIBLINGS);
assert_string_equal(str,
@@ -391,6 +405,55 @@ test_path(void **state)
"}\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
diff --git a/tests/utests/data/test_parser_json.c b/tests/utests/data/test_parser_json.c
index d341e31..8feed9c 100644
--- a/tests/utests/data/test_parser_json.c
+++ b/tests/utests/data/test_parser_json.c
@@ -1,9 +1,10 @@
-/*
+/**
* @file test_parser_json.c
- * @author: Radek Krejci <rkrejci@cesnet.cz>
- * @brief unit tests for functions from parser_xml.c
+ * @author Radek Krejci <rkrejci@cesnet.cz>
+ * @author Michal Vasko <mvasko@cesnet.cz>
+ * @brief unit tests for JSON parser
*
- * Copyright (c) 2019 CESNET, z.s.p.o.
+ * 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.
@@ -44,7 +45,10 @@ setup(void **state)
"leaf-list ll1 { type uint8; }"
"leaf foo2 { type string; default \"default-val\"; }"
"leaf foo3 { type uint32; }"
- "notification n2;}";
+ "leaf foo4 { type uint64; }"
+ "rpc r1 {input {leaf l1 {type string;} leaf l2 {type string;}}}"
+ "notification n2;"
+ "}";
UTEST_SETUP;
@@ -160,6 +164,7 @@ test_leaf(void **state)
/* 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.", "Path \"/@a:foo/@a:hi\nt\", line number 1.");
}
static void
@@ -427,12 +432,10 @@ test_list(void **state)
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);
-
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);
@@ -447,11 +450,16 @@ test_list(void **state)
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);
-
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);
@@ -460,7 +468,6 @@ test_list(void **state)
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);
}
@@ -516,6 +523,25 @@ test_opaq(void **state)
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,
@@ -555,11 +581,12 @@ test_opaq(void **state)
/* 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\".", "Data location \"/@a:foo\".");
+ "Unknown module of node \"@a:foo\".", "Path \"/\".");
+ CHECK_LOG_CTX("Missing JSON data instance to be coupled with @a:foo metadata.", "Data location \"/@a:foo\", line number 1.");
/* empty name */
PARSER_CHECK_ERROR("{\"@a:foo\":{\"\":0}}", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
- "A JSON object member name cannot be a zero-length string.", "Line number 1.");
+ "JSON object member name cannot be a zero-length string.", "Data location \"/@a:foo\", line number 1.");
/* opaque data tree format print */
data =
@@ -626,6 +653,7 @@ 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;
@@ -675,8 +703,16 @@ test_rpc(void **state)
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
lyd_free_all(tree);
- /* wrong namespace, element name, whatever... */
- /* TODO */
+ /* 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
@@ -772,6 +808,112 @@ test_reply(void **state)
/* 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\".", "Path \"/a:c/x/@a:hint\", line number 1.");
+}
+
int
main(void)
{
@@ -787,6 +929,10 @@ main(void)
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);
diff --git a/tests/utests/data/test_parser_xml.c b/tests/utests/data/test_parser_xml.c
index 7defd9c..4f33f00 100644
--- a/tests/utests/data/test_parser_xml.c
+++ b/tests/utests/data/test_parser_xml.c
@@ -31,6 +31,7 @@ setup(void **state)
" namespace urn:tests:a;\n"
" prefix a;\n"
" yang-version 1.1;\n"
+ " import ietf-yang-metadata {prefix md;}"
" 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;}}"
@@ -42,9 +43,12 @@ setup(void **state)
" notification n1 { leaf nl {type string;}}}\n"
" container cp {presence \"container switch\"; leaf y {type string;} leaf z {type int8;}}\n"
" anydata any {config false;}\n"
+ " anyxml anyx;\n"
" leaf foo2 { type string; default \"default-val\"; }\n"
" leaf foo3 { type uint32; }\n"
- " notification n2;}";
+ " notification n2;"
+ " md:annotation attr {type enumeration {enum val;}}"
+ "}";
UTEST_SETUP;
@@ -122,6 +126,7 @@ static void
test_anydata(void **state)
{
const char *data;
+ char *str;
struct lyd_node *tree;
data = "<any xmlns=\"urn:tests:a\">\n"
@@ -145,6 +150,49 @@ test_anydata(void **state)
"</any>\n";
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data_expected);
+
+ assert_int_equal(LY_SUCCESS, lyd_any_value_str(tree, &str));
+ lyd_free_all(tree);
+
+ assert_int_equal(LY_SUCCESS, lyd_new_path2(NULL, UTEST_LYCTX, "/a:any", str, strlen(str), LYD_ANYDATA_XML, 0, &tree, NULL));
+ free(str);
+ CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data_expected);
+ lyd_free_all(tree);
+}
+
+static void
+test_anyxml(void **state)
+{
+ const char *data;
+ char *str;
+ struct lyd_node *tree;
+
+ data = "<anyx xmlns=\"urn:tests:a\">\n"
+ " <element1>\n"
+ " <element2 x:attr2=\"test\" xmlns:x=\"urn:x\">data</element2>\n"
+ " </element1>\n"
+ " <element1a/>\n"
+ "</anyx>\n";
+ CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
+ assert_non_null(tree);
+ tree = tree->next;
+
+ const char *data_expected =
+ "<anyx xmlns=\"urn:tests:a\">\n"
+ " <element1>\n"
+ " <element2 xmlns:x=\"urn:x\" x:attr2=\"test\">data</element2>\n"
+ " </element1>\n"
+ " <element1a/>\n"
+ "</anyx>\n";
+
+ CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data_expected);
+
+ assert_int_equal(LY_SUCCESS, lyd_any_value_str(tree, &str));
+ lyd_free_all(tree);
+
+ assert_int_equal(LY_SUCCESS, lyd_new_path2(NULL, UTEST_LYCTX, "/a:anyx", str, strlen(str), LYD_ANYDATA_XML, 0, &tree, NULL));
+ free(str);
+ CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data_expected);
lyd_free_all(tree);
}
@@ -170,17 +218,21 @@ test_list(void **state)
/* missing keys */
PARSER_CHECK_ERROR("<l1 xmlns=\"urn:tests:a\"><c>1</c><b>b</b></l1>", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
"List instance is missing its key \"a\".", "Data location \"/a:l1[b='b'][c='1']\", line number 1.");
+ CHECK_LOG_CTX("Invalid position of the key \"b\" in a list.", NULL);
PARSER_CHECK_ERROR("<l1 xmlns=\"urn:tests:a\"><a>a</a></l1>", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
"List instance is missing its key \"b\".", "Data location \"/a:l1[a='a']\", line number 1.");
PARSER_CHECK_ERROR("<l1 xmlns=\"urn:tests:a\"><b>b</b><a>a</a></l1>", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
"List instance is missing its key \"c\".", "Data location \"/a:l1[a='a'][b='b']\", line number 1.");
+ CHECK_LOG_CTX("Invalid position of the key \"a\" in a list.", NULL);
/* key duplicate */
PARSER_CHECK_ERROR("<l1 xmlns=\"urn:tests:a\"><c>1</c><b>b</b><a>a</a><c>1</c></l1>", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
"Duplicate instance of \"c\".",
"Data location \"/a:l1[a='a'][b='b'][c='1'][c='1']/c\", line number 1.");
+ CHECK_LOG_CTX("Invalid position of the key \"a\" in a list.", NULL);
+ CHECK_LOG_CTX("Invalid position of the key \"b\" in a list.", NULL);
/* keys order */
CHECK_PARSE_LYD("<l1 xmlns=\"urn:tests:a\"><d>d</d><a>a</a><c>1</c><b>b</b></l1>", 0, LYD_VALIDATE_PRESENT, tree);
@@ -209,6 +261,7 @@ test_list(void **state)
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("Invalid position of the key \"a\" in a list.", NULL);
+ CHECK_LOG_CTX("Invalid position of the key \"b\" in a list.", NULL);
lyd_free_all(tree);
PARSER_CHECK_ERROR(data, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
@@ -250,14 +303,14 @@ test_opaq(void **state)
/* 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_XML, "foo3", 0, 0, NULL, 0, "");
+ CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 0, LY_VALUE_XML, "foo3", 0, 0, NULL, 1, "");
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, "<foo3 xmlns=\"urn:tests:a\"/>\n");
lyd_free_all(tree);
/* list, opaq flag */
data = "<l1 xmlns=\"urn:tests:a\"/>";
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_XML, "l1", 0, 0, NULL, 0, "");
+ CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 0, LY_VALUE_XML, "l1", 0, 0, NULL, 1, "");
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, "<l1 xmlns=\"urn:tests:a\"/>\n");
lyd_free_all(tree);
@@ -273,7 +326,7 @@ test_opaq(void **state)
/* 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_XML, "l1", 0, 0, NULL, 0, "");
+ CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 0x1, LY_VALUE_XML, "l1", 0, 0, NULL, 1, "");
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data);
lyd_free_all(tree);
@@ -289,7 +342,7 @@ test_opaq(void **state)
/* 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_XML, "l1", 0, 0, NULL, 0, "");
+ CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 0x1, LY_VALUE_XML, "l1", 0, 0, NULL, 1, "");
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data);
lyd_free_all(tree);
@@ -300,7 +353,7 @@ test_opaq(void **state)
" <c xmld:id=\"D\">1</c>\n"
"</a>\n",
LYD_XML, LYD_PARSE_OPAQ, LYD_VALIDATE_PRESENT, &tree));
- CHECK_LOG_CTX("Unknown XML prefix \"xmld\".", "Line number 3.");
+ CHECK_LOG_CTX("Unknown XML prefix \"xmld\".", "Data location \"/a\", line number 3.");
}
static void
@@ -358,10 +411,10 @@ test_rpc(void **state)
node = lyd_child(node);
/* z has no value */
- CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)node, 0x1, 0, LY_VALUE_XML, "z", 0, 0, NULL, 0, "");
+ CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)node, 0x1, 0, LY_VALUE_XML, "z", 0, 0, NULL, 1, "");
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_XML, "l1", 0, 0, NULL, 0, "");
+ CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)node, 0x1, 0x1, LY_VALUE_XML, "l1", 0, 0, NULL, 1, "");
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS,
"<edit-config xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
@@ -554,10 +607,10 @@ test_netconf_rpc(void **state)
node = lyd_child(node);
/* z has no value */
- CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)node, 0x1, 0, LY_VALUE_XML, "z", 0, 0, NULL, 0, "");
+ CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)node, 0x1, 0, LY_VALUE_XML, "z", 0, 0, NULL, 1, "");
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_XML, "l1", 0, 0, NULL, 0, "");
+ CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)node, 0x1, 0x1, LY_VALUE_XML, "l1", 0, 0, NULL, 1, "");
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS,
"<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"25\"/>\n");
@@ -581,8 +634,33 @@ test_netconf_rpc(void **state)
lyd_free_all(tree);
lyd_free_all(op);
- /* wrong namespace, element name, whatever... */
- /* TODO */
+ /* invalid anyxml nested metadata value */
+ data = "<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"1\" pid=\"4114692032\">\n"
+ " <copy-config>\n"
+ " <target>\n"
+ " <running/>\n"
+ " </target>\n"
+ " <source>\n"
+ " <config>\n"
+ " <l1 xmlns=\"urn:tests:a\" xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
+ " <a>val_a</a>\n"
+ " <b>val_b</b>\n"
+ " <c>5</c>\n"
+ " <cont nc:operation=\"merge\">\n"
+ " <e nc:operation=\"merge2\">false</e>\n"
+ " </cont>\n"
+ " </l1>\n"
+ " </config>\n"
+ " </source>\n"
+ " </copy-config>\n"
+ "</rpc>\n";
+ assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
+ assert_int_equal(LY_EVALID, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_NETCONF, &tree, &op));
+ ly_in_free(in, 0);
+ CHECK_LOG_CTX("Invalid enumeration value \"merge2\".",
+ "Path \"/ietf-netconf:copy-config/source/config/a:l1[a='val_a'][b='val_b'][c='5']/cont/e/@ietf-netconf:operation\", line number 13.");
+ lyd_free_all(tree);
+ assert_null(op);
}
static void
@@ -678,6 +756,22 @@ test_netconf_reply_or_notification(void **state)
lyd_free_all(tree);
lyd_free_all(op2);
+ /* notification with a different order */
+ data = "<notification xmlns=\"urn:ietf:params:xml:ns:netconf:notification:1.0\">\n"
+ "<c xmlns=\"urn:tests:a\">\n"
+ " <n1>\n"
+ " <nl>value</nl>\n"
+ " </n1>\n"
+ "</c>\n"
+ "<eventTime>2010-12-06T08:00:01Z</eventTime>\n"
+ "</notification>\n";
+ assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
+ assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_NOTIF_NETCONF, &tree, &op2));
+ ly_in_free(in, 0);
+
+ lyd_free_all(tree);
+ lyd_free_all(op2);
+
/* parse a data reply */
data = "<rpc-reply message-id=\"55\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
" <al xmlns=\"urn:tests:a\">25</al>\n"
@@ -739,6 +833,64 @@ test_netconf_reply_or_notification(void **state)
}
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 = "<input xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-nmda\">"
+ "<datastore xmlns:ds=\"urn:ietf:params:xml:ns:yang:ietf-datastores\">ds:running</datastore>"
+ "<config>"
+ "<cp xmlns=\"urn:tests:a\"><z xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\" nc:operation=\"replace\"/></cp>"
+ "<l1 xmlns=\"urn:tests:a\" xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\" nc:operation=\"replace\">"
+ "<a>val_a</a><b>val_b</b><c>val_c</c>"
+ "</l1>"
+ "</config></input>";
+ assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
+ assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, tree, in, LYD_XML, LYD_TYPE_RPC_RESTCONF, &envp, NULL));
+ ly_in_free(in, 0);
+
+ /* the same just connected to the edit-data RPC */
+ data = "<edit-data xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-nmda\">"
+ "<datastore xmlns:ds=\"urn:ietf:params:xml:ns:yang:ietf-datastores\">ds:running</datastore>"
+ "<config>"
+ "<cp xmlns=\"urn:tests:a\"><z xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\" nc:operation=\"replace\"/></cp>"
+ "<l1 xmlns=\"urn:tests:a\" xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\" nc:operation=\"replace\">"
+ "<a>val_a</a><b>val_b</b><c>val_c</c>"
+ "</l1>"
+ "</config></edit-data>";
+ CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
+ lyd_free_all(tree);
+ lyd_free_all(envp);
+}
+
+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 = "<output xmlns=\"urn:tests:a\"><al>25</al></output>";
+ 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_XML, LYD_TYPE_REPLY_RESTCONF, &envp, NULL));
+ ly_in_free(in, 0);
+
+ /* connected to the RPC with the parent */
+ data = "<c xmlns=\"urn:tests:a\"><act><al>25</al></act></c>";
+ CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
+ lyd_free_all(tree);
+ lyd_free_all(envp);
+}
+
+static void
test_filter_attributes(void **state)
{
const char *data;
@@ -812,12 +964,58 @@ test_data_skip(void **state)
lyd_free_all(tree);
}
+static void
+test_metadata(void **state)
+{
+ const char *data;
+ struct lyd_node *tree;
+
+ /* invalid metadata value */
+ data = "<c xmlns=\"urn:tests:a\" xmlns:a=\"urn:tests:a\"><x a:attr=\"value\">xval</x></c>";
+ assert_int_equal(LY_EVALID, lyd_parse_data_mem(_UC->ctx, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
+ assert_null(tree);
+ CHECK_LOG_CTX("Invalid enumeration value \"value\".", "Path \"/a:c/x/@a:attr\", line number 1.");
+}
+
+static void
+test_subtree(void **state)
+{
+ const char *data;
+ struct ly_in *in;
+ struct lyd_node *tree;
+
+ /* prepare data with the parent */
+ data = "<l1 xmlns=\"urn:tests:a\">\n"
+ " <a>val_a</a>\n"
+ " <b>val_b</b>\n"
+ " <c>1</c>\n"
+ "</l1>\n";
+ assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
+
+ /* parse a subtree of it */
+ data = "<cont xmlns=\"urn:tests:a\">\n"
+ " <e>true</e>\n"
+ "</cont>\n";
+ assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
+ assert_int_equal(LY_SUCCESS, lyd_parse_data(UTEST_LYCTX, tree, in, LYD_XML, 0, LYD_VALIDATE_PRESENT, NULL));
+ ly_in_free(in, 0);
+
+ /* parse another container, fails */
+ assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
+ assert_int_equal(LY_EVALID, lyd_parse_data(UTEST_LYCTX, tree, in, LYD_XML, 0, LYD_VALIDATE_PRESENT, NULL));
+ ly_in_free(in, 0);
+ CHECK_LOG_CTX("Duplicate instance of \"cont\".", "Data location \"/a:l1[a='val_a'][b='val_b'][c='1']/cont\".");
+
+ lyd_free_all(tree);
+}
+
int
main(void)
{
const struct CMUnitTest tests[] = {
UTEST(test_leaf, setup),
UTEST(test_anydata, setup),
+ UTEST(test_anyxml, setup),
UTEST(test_list, setup),
UTEST(test_container, setup),
UTEST(test_opaq, setup),
@@ -828,8 +1026,12 @@ main(void)
UTEST(test_netconf_rpc, setup),
UTEST(test_netconf_action, setup),
UTEST(test_netconf_reply_or_notification, setup),
+ UTEST(test_restconf_rpc, setup),
+ UTEST(test_restconf_reply, setup),
UTEST(test_filter_attributes, setup),
UTEST(test_data_skip, setup),
+ UTEST(test_metadata, setup),
+ UTEST(test_subtree, setup),
};
return cmocka_run_group_tests(tests, NULL, NULL);
diff --git a/tests/utests/data/test_printer_xml.c b/tests/utests/data/test_printer_xml.c
index d533c41..6213a37 100644
--- a/tests/utests/data/test_printer_xml.c
+++ b/tests/utests/data/test_printer_xml.c
@@ -145,7 +145,8 @@ test_anydata(void **state)
" <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"
+ "defs:attr1=\"defaults:val\" attr2=\"/defaults:node/defs:node2\">\n"
+ " </elem2>\n"
" </elem1>\n"
" </cont>\n"
"</any>\n";
diff --git a/tests/utests/data/test_tree_data.c b/tests/utests/data/test_tree_data.c
index 27dba42..494fdf3 100644
--- a/tests/utests/data/test_tree_data.c
+++ b/tests/utests/data/test_tree_data.c
@@ -1,9 +1,9 @@
/**
* @file test_tree_data.c
- * @author: Radek Krejci <rkrejci@cesnet.cz>
- * @brief unit tests for functions from tress_data.c
+ * @author Radek Krejci <rkrejci@cesnet.cz>
+ * @brief unit tests for functions from tree_data.c
*
- * Copyright (c) 2018-2019 CESNET, z.s.p.o.
+ * 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.
@@ -100,7 +100,7 @@ test_compare(void **state)
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, 0));
+ 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);
@@ -145,6 +145,14 @@ test_compare(void **state)
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
@@ -196,7 +204,7 @@ test_compare_diff_ctx(void **state)
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(tree1, tree2, 0));
+ assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, 0));
lyd_free_all(tree1);
lyd_free_all(tree2);
@@ -210,7 +218,7 @@ test_compare_diff_ctx(void **state)
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(tree1, tree2, 0));
+ assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, 0));
lyd_free_all(tree1);
lyd_free_all(tree2);
@@ -329,8 +337,7 @@ test_dup(void **state)
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(((struct lyd_node_inner *)((struct lyd_node_inner *)tree1->next)->child)->child, NULL,
- LYD_DUP_WITH_PARENTS, &tree2));
+ 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);
@@ -352,8 +359,8 @@ test_dup(void **state)
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(((struct lyd_node_inner *)((struct lyd_node_inner *)tree1->next)->child)->child,
- (struct lyd_node_inner *)tree2, LYD_DUP_WITH_PARENTS, NULL));
+ 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);
@@ -363,6 +370,8 @@ test_dup(void **state)
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);
lyd_free_all(tree1);
}
@@ -488,6 +497,11 @@ test_find_path(void **state)
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.", "Schema location \"/c:cont\".");
+ assert_int_equal(LY_SUCCESS, lyd_find_path(root, "nexthop[gateway='2100::1']", 0, NULL));
+
lyd_free_all(root);
}
@@ -525,6 +539,7 @@ test_data_hash(void **state)
/* 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\".", "Data location \"/test-data-hash:c/ll[.='']\", line number 1.");
lyd_free_all(tree);
}
diff --git a/tests/utests/data/test_validation.c b/tests/utests/data/test_validation.c
index 415e16a..d0dcae5 100644
--- a/tests/utests/data/test_validation.c
+++ b/tests/utests/data/test_validation.c
@@ -1154,6 +1154,92 @@ test_must(void **state)
CHECK_LOG_CTX_APPTAG("l leaf is not left", "Data location \"/i:cont/l3\".", "not-left");
}
+static void
+test_multi_error(void **state)
+{
+ struct lyd_node *tree;
+ const char *schema =
+ "module ii {\n"
+ " namespace urn:tests:ii;\n"
+ " prefix ii;\n"
+ " yang-version 1.1;\n"
+ "\n"
+ " container cont {\n"
+ " leaf l {\n"
+ " type string;\n"
+ " }\n"
+ " leaf l2 {\n"
+ " must \"../l = 'right'\";\n"
+ " type string;\n"
+ " }\n"
+ " leaf l3 {\n"
+ " must \"../l = 'left'\" {\n"
+ " error-app-tag \"not-left\";\n"
+ " error-message \"l leaf is not left\";\n"
+ " }\n"
+ " type string;\n"
+ " }\n"
+ " leaf-list ll {\n"
+ " type uint32;\n"
+ " min-elements 2;\n"
+ " }\n"
+ " }\n"
+ "}";
+ const char *data;
+
+ UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
+
+ /* xml */
+ data =
+ "<cont xmlns=\"urn:tests:ii\">\n"
+ " <l>wrong</l>\n"
+ " <l>wrong2</l>\n"
+ " <l2>val</l2>\n"
+ " <l3>val</l3>\n"
+ " <ll>ahoy</ll>\n"
+ "</cont>\n";
+ CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT | LYD_VALIDATE_MULTI_ERROR, LY_EVALID, tree);
+ CHECK_LOG_CTX_APPTAG("Too few \"ll\" instances.", "Schema location \"/ii:cont/ll\".", "too-few-elements");
+ CHECK_LOG_CTX_APPTAG("l leaf is not left", "Data location \"/ii:cont/l3\".", "not-left");
+ CHECK_LOG_CTX_APPTAG("Must condition \"../l = 'right'\" not satisfied.", "Data location \"/ii:cont/l2\".", "must-violation");
+ CHECK_LOG_CTX_APPTAG("Invalid type uint32 value \"ahoy\".", "Data location \"/ii:cont/ll\", line number 6.", NULL);
+
+ /* json */
+ data = "{\n"
+ " \"ii:cont\": {\n"
+ " \"l\": \"wrong\",\n"
+ " \"l\": \"wrong2\",\n"
+ " \"l2\": \"val\",\n"
+ " \"l3\": \"val\",\n"
+ " \"ll\": [\"ahoy\"]\n"
+ " }\n"
+ "}\n";
+ CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT | LYD_VALIDATE_MULTI_ERROR, LY_EVALID, tree);
+ CHECK_LOG_CTX_APPTAG("Too few \"ll\" instances.", "Schema location \"/ii:cont/ll\".", "too-few-elements");
+ CHECK_LOG_CTX_APPTAG("l leaf is not left", "Data location \"/ii:cont/l3\".", "not-left");
+ CHECK_LOG_CTX_APPTAG("Must condition \"../l = 'right'\" not satisfied.", "Data location \"/ii:cont/l2\".", "must-violation");
+ CHECK_LOG_CTX_APPTAG("Invalid non-number-encoded uint32 value \"ahoy\".", "Data location \"/ii:cont/ll\", line number 7.", NULL);
+
+ /* validation */
+ data = "{\n"
+ " \"ii:cont\": {\n"
+ " \"l\": \"wrong\",\n"
+ " \"l\": \"wrong2\",\n"
+ " \"l2\": \"val\",\n"
+ " \"l3\": \"val\",\n"
+ " \"ll\": [25]\n"
+ " }\n"
+ "}\n";
+ CHECK_PARSE_LYD_PARAM(data, LYD_JSON, LYD_PARSE_ONLY, 0, LY_SUCCESS, tree);
+ assert_int_equal(LY_EVALID, lyd_validate_all(&tree, NULL, LYD_VALIDATE_PRESENT | LYD_VALIDATE_MULTI_ERROR, NULL));
+ lyd_free_tree(tree);
+ CHECK_LOG_CTX_APPTAG("Too few \"ll\" instances.", "Schema location \"/ii:cont/ll\".", "too-few-elements");
+ CHECK_LOG_CTX_APPTAG("l leaf is not left", "Data location \"/ii:cont/l3\".", "not-left");
+ CHECK_LOG_CTX_APPTAG("Must condition \"../l = 'right'\" not satisfied.", "Data location \"/ii:cont/l2\".", "must-violation");
+ CHECK_LOG_CTX_APPTAG("Duplicate instance of \"l\".", "Data location \"/ii:cont/l\".", NULL);
+ CHECK_LOG_CTX_APPTAG("Duplicate instance of \"l\".", "Data location \"/ii:cont/l\".", NULL);
+}
+
const char *schema_j =
"module j {\n"
" namespace urn:tests:j;\n"
@@ -1212,6 +1298,7 @@ test_action(void **state)
struct lyd_node *tree, *op_tree;
UTEST_ADD_MODULE(schema_j, LYS_IN_YANG, feats_j, NULL);
+ UTEST_LOG_CTX_CLEAN;
assert_int_equal(LY_SUCCESS, ly_in_new_memory(
"<cont xmlns=\"urn:tests:j\">\n"
@@ -1304,6 +1391,7 @@ test_reply(void **state)
struct lyd_node *tree, *op_tree;
UTEST_ADD_MODULE(schema_j, LYS_IN_YANG, feats_j, NULL);
+ UTEST_LOG_CTX_CLEAN;
assert_int_equal(LY_SUCCESS, ly_in_new_memory(
"<cont xmlns=\"urn:tests:j\">\n"
@@ -1422,7 +1510,7 @@ test_case(void **state)
" }\n"
"}\n", LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
CHECK_LOG_CTX("Data for both cases \"v0\" and \"v2\" exist.",
- "Data location \"/k:ch\", line number 5.");
+ "Data location \"/k:ch\", line number 6.");
CHECK_PARSE_LYD_PARAM(
"{\n"
@@ -1432,7 +1520,7 @@ test_case(void **state)
" }\n"
"}\n", LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
CHECK_LOG_CTX("Data for both cases \"v0\" and \"v2\" exist.",
- "Data location \"/k:ch\", line number 5.");
+ "Data location \"/k:ch\", line number 6.");
}
int
@@ -1450,6 +1538,7 @@ main(void)
UTEST(test_defaults),
UTEST(test_state),
UTEST(test_must),
+ UTEST(test_multi_error),
UTEST(test_action),
UTEST(test_rpc),
UTEST(test_reply),
diff --git a/tests/utests/extensions/test_metadata.c b/tests/utests/extensions/test_metadata.c
index 39d29be..f1edd29 100644
--- a/tests/utests/extensions/test_metadata.c
+++ b/tests/utests/extensions/test_metadata.c
@@ -53,7 +53,7 @@ test_yang(void **state)
"md:annotation aa;}";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Ext plugin \"ly2 metadata v1\": Missing mandatory keyword \"type\" as a child of \"md:annotation aa\".",
- "/aa:{extension='md:annotation'}/aa");
+ "Path \"/aa:{extension='md:annotation'}/aa\".");
/* not allowed substatement */
data = "module aa {yang-version 1.1; namespace urn:tests:extensions:metadata:aa; prefix aa;"
@@ -61,7 +61,7 @@ test_yang(void **state)
"md:annotation aa {default x;}}";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Invalid keyword \"default\" as a child of \"md:annotation aa\" extension instance.",
- "/aa:{extension='md:annotation'}/aa");
+ "Path \"/aa:{extension='md:annotation'}/aa\".");
/* invalid cardinality of units substatement */
data = "module aa {yang-version 1.1; namespace urn:tests:extensions:metadata:aa; prefix aa;"
@@ -69,7 +69,7 @@ test_yang(void **state)
"md:annotation aa {type string; units x; units y;}}";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Duplicate keyword \"units\".",
- "/aa:{extension='md:annotation'}/aa");
+ "Path \"/aa:{extension='md:annotation'}/aa\".");
/* invalid cardinality of status substatement */
data = "module aa {yang-version 1.1; namespace urn:tests:extensions:metadata:aa; prefix aa;"
@@ -77,7 +77,7 @@ test_yang(void **state)
"md:annotation aa {type string; status current; status obsolete;}}";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Duplicate keyword \"status\".",
- "/aa:{extension='md:annotation'}/aa");
+ "Path \"/aa:{extension='md:annotation'}/aa\".");
/* invalid cardinality of status substatement */
data = "module aa {yang-version 1.1; namespace urn:tests:extensions:metadata:aa; prefix aa;"
@@ -85,7 +85,7 @@ test_yang(void **state)
"md:annotation aa {type string; type uint8;}}";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Duplicate keyword \"type\".",
- "/aa:{extension='md:annotation'}/aa");
+ "Path \"/aa:{extension='md:annotation'}/aa\".");
/* duplication of the same annotation */
data = "module aa {yang-version 1.1; namespace urn:tests:extensions:metadata:aa; prefix aa;"
@@ -93,7 +93,7 @@ test_yang(void **state)
"md:annotation aa {type string;} md:annotation aa {type uint8;}}";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Ext plugin \"ly2 metadata v1\": Extension md:annotation is instantiated multiple times.",
- "/aa:{extension='md:annotation'}/aa");
+ "Path \"/aa:{extension='md:annotation'}/aa\".");
}
static void
@@ -134,7 +134,7 @@ test_yin(void **state)
"</module>";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YIN, NULL));
CHECK_LOG_CTX("Ext plugin \"ly2 metadata v1\": Missing mandatory keyword \"type\" as a child of \"md:annotation aa\".",
- "/aa:{extension='md:annotation'}/aa");
+ "Path \"/aa:{extension='md:annotation'}/aa\".");
/* not allowed substatement */
data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"aa\">\n"
@@ -145,7 +145,7 @@ test_yin(void **state)
"</md:annotation></module>";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YIN, NULL));
CHECK_LOG_CTX("Invalid keyword \"default\" as a child of \"md:annotation aa\" extension instance.",
- "/aa:{extension='md:annotation'}/aa");
+ "Path \"/aa:{extension='md:annotation'}/aa\".");
/* invalid cardinality of units substatement */
data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"aa\">\n"
@@ -158,7 +158,7 @@ test_yin(void **state)
"</md:annotation></module>";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YIN, NULL));
CHECK_LOG_CTX("Duplicate keyword \"units\".",
- "/aa:{extension='md:annotation'}/aa");
+ "Path \"/aa:{extension='md:annotation'}/aa\".");
/* invalid cardinality of status substatement */
data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"aa\">\n"
@@ -171,7 +171,7 @@ test_yin(void **state)
"</md:annotation></module>";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YIN, NULL));
CHECK_LOG_CTX("Duplicate keyword \"status\".",
- "/aa:{extension='md:annotation'}/aa");
+ "Path \"/aa:{extension='md:annotation'}/aa\".");
/* invalid cardinality of status substatement */
data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"aa\">\n"
@@ -183,7 +183,7 @@ test_yin(void **state)
"</md:annotation></module>";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YIN, NULL));
CHECK_LOG_CTX("Duplicate keyword \"type\".",
- "/aa:{extension='md:annotation'}/aa");
+ "Path \"/aa:{extension='md:annotation'}/aa\".");
/* duplication of the same annotation */
data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"aa\">\n"
@@ -196,7 +196,7 @@ test_yin(void **state)
"</md:annotation></module>";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YIN, NULL));
CHECK_LOG_CTX("Ext plugin \"ly2 metadata v1\": Extension md:annotation is instantiated multiple times.",
- "/aa:{extension='md:annotation'}/aa");
+ "Path \"/aa:{extension='md:annotation'}/aa\".");
}
int
diff --git a/tests/utests/extensions/test_nacm.c b/tests/utests/extensions/test_nacm.c
index 1c999fb..5f7028e 100644
--- a/tests/utests/extensions/test_nacm.c
+++ b/tests/utests/extensions/test_nacm.c
@@ -58,7 +58,7 @@ test_deny_all(void **state)
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Ext plugin \"ly2 NACM v1\": "
"Extension nacm:default-deny-all is allowed only in a data nodes, but it is placed in \"module\" statement.",
- "/b:{extension='nacm:default-deny-all'}");
+ "Path \"/b:{extension='nacm:default-deny-all'}\".");
/* invalid */
data = "module aa {yang-version 1.1; namespace urn:tests:extensions:nacm:aa; prefix en;"
@@ -67,7 +67,7 @@ test_deny_all(void **state)
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Ext plugin \"ly2 NACM v1\": "
"Extension nacm:default-deny-write is mixed with nacm:default-deny-all.",
- "/aa:l/{extension='nacm:default-deny-all'}");
+ "Path \"/aa:l/{extension='nacm:default-deny-all'}\".");
}
static void
@@ -100,7 +100,7 @@ test_deny_write(void **state)
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Ext plugin \"ly2 NACM v1\": "
"Extension nacm:default-deny-write is not allowed in notification statement.",
- "/b:notif/{extension='nacm:default-deny-write'}");
+ "Path \"/b:notif/{extension='nacm:default-deny-write'}\".");
/* invalid */
data = "module aa {yang-version 1.1; namespace urn:tests:extensions:nacm:aa; prefix en;"
@@ -109,7 +109,7 @@ test_deny_write(void **state)
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Ext plugin \"ly2 NACM v1\": "
"Extension nacm:default-deny-write is instantiated multiple times.",
- "/aa:l/{extension='nacm:default-deny-write'}");
+ "Path \"/aa:l/{extension='nacm:default-deny-write'}\".");
}
int
diff --git a/tests/utests/extensions/test_schema_mount.c b/tests/utests/extensions/test_schema_mount.c
index be879ec..17a4c94 100644
--- a/tests/utests/extensions/test_schema_mount.c
+++ b/tests/utests/extensions/test_schema_mount.c
@@ -75,7 +75,7 @@ test_schema(void **state)
assert_int_equal(LY_EINVAL, lys_parse_mem(UTEST_LYCTX, schema, LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": "
"Extension \"yangmnt:mount-point\" instance not allowed in YANG version 1 module.",
- "/sm:root/{extension='yangmnt:mount-point'}/root");
+ "Path \"/sm:root/{extension='yangmnt:mount-point'}/root\".");
schema =
"module sm {\n"
@@ -92,7 +92,7 @@ test_schema(void **state)
assert_int_equal(LY_EINVAL, lys_parse_mem(UTEST_LYCTX, schema, LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": "
"Extension \"yangmnt:mount-point\" instance allowed only in container or list statement.",
- "/sm:{extension='yangmnt:mount-point'}/root");
+ "Path \"/sm:{extension='yangmnt:mount-point'}/root\".");
schema =
"module sm {\n"
@@ -114,7 +114,7 @@ test_schema(void **state)
assert_int_equal(LY_EINVAL, lys_parse_mem(UTEST_LYCTX, schema, LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": "
"Extension \"yangmnt:mount-point\" instance allowed only in container or list statement.",
- "/sm:root/l/{extension='yangmnt:mount-point'}/root");
+ "Path \"/sm:root/l/{extension='yangmnt:mount-point'}/root\".");
schema =
"module sm {\n"
@@ -138,7 +138,7 @@ test_schema(void **state)
assert_int_equal(LY_EINVAL, lys_parse_mem(UTEST_LYCTX, schema, LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": "
"Multiple extension \"yangmnt:mount-point\" instances.",
- "/sm:l/{extension='yangmnt:mount-point'}/root");
+ "Path \"/sm:l/{extension='yangmnt:mount-point'}/root\".");
/* valid */
schema =
@@ -410,25 +410,25 @@ test_parse_invalid(void **state)
CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data);
CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": "
"Mandatory node \"type\" instance does not exist.",
- "Schema location \"/ietf-interfaces:interfaces/interface/type\".");
+ "Data location \"/ietf-interfaces:interfaces/interface[name='bu']\".");
CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data);
CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": "
"Mandatory node \"type\" instance does not exist.",
- "Schema location \"/ietf-interfaces:interfaces/interface/type\".");
+ "Data location \"/ietf-interfaces:interfaces/interface[name='bu']\".");
/* same validation fail in separate validation */
CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT | LYD_PARSE_ONLY, 0, LY_SUCCESS, data);
assert_int_equal(LY_EVALID, lyd_validate_all(&data, NULL, LYD_VALIDATE_PRESENT, NULL));
CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": "
"Mandatory node \"type\" instance does not exist.",
- "Schema location \"/ietf-interfaces:interfaces/interface/type\".");
+ "Data location \"/ietf-interfaces:interfaces/interface[name='bu']\".");
lyd_free_siblings(data);
CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT | LYD_PARSE_ONLY, 0, LY_SUCCESS, data);
assert_int_equal(LY_EVALID, lyd_validate_all(&data, NULL, LYD_VALIDATE_PRESENT, NULL));
CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": "
"Mandatory node \"type\" instance does not exist.",
- "Schema location \"/ietf-interfaces:interfaces/interface/type\".");
+ "Data location \"/ietf-interfaces:interfaces/interface[name='bu']\".");
lyd_free_siblings(data);
/* success */
@@ -878,7 +878,7 @@ test_parse_shared(void **state)
CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data);
CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": "
"Shared-schema yang-library content-id \"2\" differs from \"1\" used previously.",
- "/ietf-yang-library:yang-library/content-id");
+ "Path \"/ietf-yang-library:yang-library/content-id\".");
/* data for 2 mount points */
ly_ctx_set_ext_data_clb(UTEST_LYCTX, test_ext_data_clb,
@@ -1549,6 +1549,108 @@ test_new(void **state)
lyd_free_siblings(data);
}
+static void
+test_lys_getnext(void **state)
+{
+ const struct lysc_node *parent, *node;
+ struct ly_ctx *sm_ctx;
+
+ ly_ctx_set_ext_data_clb(UTEST_LYCTX, test_ext_data_clb,
+ "<yang-library xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\" "
+ " xmlns:ds=\"urn:ietf:params:xml:ns:yang:ietf-datastores\">"
+ " <module-set>"
+ " <name>test-set</name>"
+ " <module>"
+ " <name>ietf-datastores</name>"
+ " <revision>2018-02-14</revision>"
+ " <namespace>urn:ietf:params:xml:ns:yang:ietf-datastores</namespace>"
+ " </module>"
+ " <module>"
+ " <name>ietf-yang-library</name>"
+ " <revision>2019-01-04</revision>"
+ " <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-library</namespace>"
+ " </module>"
+ " <module>"
+ " <name>ietf-yang-schema-mount</name>"
+ " <revision>2019-01-14</revision>"
+ " <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount</namespace>"
+ " </module>"
+ " <module>"
+ " <name>ietf-interfaces</name>"
+ " <revision>2014-05-08</revision>"
+ " <namespace>urn:ietf:params:xml:ns:yang:ietf-interfaces</namespace>"
+ " </module>"
+ " <module>"
+ " <name>iana-if-type</name>"
+ " <revision>2014-05-08</revision>"
+ " <namespace>urn:ietf:params:xml:ns:yang:iana-if-type</namespace>"
+ " </module>"
+ " <module>"
+ " <name>ietf-ip</name>"
+ " <revision>2014-06-16</revision>"
+ " <namespace>urn:ietf:params:xml:ns:yang:ietf-ip</namespace>"
+ " </module>"
+ " <import-only-module>"
+ " <name>ietf-yang-types</name>"
+ " <revision>2013-07-15</revision>"
+ " <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-types</namespace>"
+ " </import-only-module>"
+ " </module-set>"
+ " <schema>"
+ " <name>test-schema</name>"
+ " <module-set>test-set</module-set>"
+ " </schema>"
+ " <datastore>"
+ " <name>ds:running</name>"
+ " <schema>test-schema</schema>"
+ " </datastore>"
+ " <datastore>"
+ " <name>ds:operational</name>"
+ " <schema>test-schema</schema>"
+ " </datastore>"
+ " <content-id>1</content-id>"
+ "</yang-library>"
+ "<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">"
+ " <module-set-id>1</module-set-id>"
+ "</modules-state>"
+ "<schema-mounts xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount\">"
+ " <mount-point>"
+ " <module>sm</module>"
+ " <label>root</label>"
+ " <shared-schema/>"
+ " </mount-point>"
+ "</schema-mounts>");
+
+ parent = lys_find_path(UTEST_LYCTX, NULL, "/sm:root", 0);
+ assert_non_null(parent);
+
+ node = lys_getnext(NULL, parent, NULL, LYS_GETNEXT_WITHSCHEMAMOUNT);
+ assert_non_null(node);
+ assert_string_equal(node->name, "schema-mounts");
+ sm_ctx = node->module->ctx;
+
+ node = lys_getnext(node, parent, NULL, LYS_GETNEXT_WITHSCHEMAMOUNT);
+ assert_non_null(node);
+ assert_string_equal(node->name, "yang-library");
+
+ node = lys_getnext(node, parent, NULL, LYS_GETNEXT_WITHSCHEMAMOUNT);
+ assert_non_null(node);
+ assert_string_equal(node->name, "modules-state");
+
+ node = lys_getnext(node, parent, NULL, LYS_GETNEXT_WITHSCHEMAMOUNT);
+ assert_non_null(node);
+ assert_string_equal(node->name, "interfaces");
+
+ node = lys_getnext(node, parent, NULL, LYS_GETNEXT_WITHSCHEMAMOUNT);
+ assert_non_null(node);
+ assert_string_equal(node->name, "interfaces-state");
+
+ node = lys_getnext(node, parent, NULL, LYS_GETNEXT_WITHSCHEMAMOUNT);
+ assert_null(node);
+
+ ly_ctx_destroy(sm_ctx);
+}
+
int
main(void)
{
@@ -1560,6 +1662,7 @@ main(void)
UTEST(test_parse_shared_parent_ref, setup),
UTEST(test_parse_config, setup),
UTEST(test_new, setup),
+ UTEST(test_lys_getnext, setup),
};
return cmocka_run_group_tests(tests, NULL, NULL);
diff --git a/tests/utests/extensions/test_structure.c b/tests/utests/extensions/test_structure.c
index 23af450..9bad7a7 100644
--- a/tests/utests/extensions/test_structure.c
+++ b/tests/utests/extensions/test_structure.c
@@ -148,7 +148,7 @@ test_schema_invalid(void **state)
"sx:structure struct {import yang;}}";
UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_EVALID);
CHECK_LOG_CTX("Invalid keyword \"import\" as a child of \"sx:structure struct\" extension instance.",
- "/a:{extension='sx:structure'}/struct");
+ "Path \"/a:{extension='sx:structure'}/struct\".");
data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix self;"
"import ietf-yang-structure-ext {prefix sx;}"
@@ -156,14 +156,14 @@ test_schema_invalid(void **state)
UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_EVALID);
CHECK_LOG_CTX("Ext plugin \"ly2 structure v1\": "
"Extension sx:structure must not be used as a non top-level statement in \"container\" statement.",
- "/a:b/{extension='sx:structure'}/struct");
+ "Path \"/a:b/{extension='sx:structure'}/struct\".");
data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix self;"
"import ietf-yang-structure-ext {prefix sx;}"
"sx:structure { container x { leaf x {type string;}}}}";
UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Extension instance \"sx:structure\" missing argument element \"name\".", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Extension instance \"sx:structure\" missing argument element \"name\".", NULL);
data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix self;"
"import ietf-yang-structure-ext {prefix sx;}"
@@ -171,7 +171,7 @@ test_schema_invalid(void **state)
"sx:structure struct { container y { leaf y {type string;}}}}";
UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_EVALID);
CHECK_LOG_CTX("Ext plugin \"ly2 structure v1\": Extension sx:structure is instantiated multiple times.",
- "/a:{extension='sx:structure'}/struct");
+ "Path \"/a:{extension='sx:structure'}/struct\".");
data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix self;"
"import ietf-yang-structure-ext {prefix sx;}"
@@ -179,7 +179,7 @@ test_schema_invalid(void **state)
"choice struct { container y { leaf y {type string;}}}}";
UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_EVALID);
CHECK_LOG_CTX("Ext plugin \"ly2 structure v1\": Extension sx:structure collides with a choice with the same identifier.",
- "/a:{extension='sx:structure'}/struct");
+ "Path \"/a:{extension='sx:structure'}/struct\".");
/* augment-structure */
data = "module a {yang-version 1.1; namespace urn:tests:extensions:structure:a; prefix a;"
@@ -199,7 +199,7 @@ test_schema_invalid(void **state)
"}}";
UTEST_INVALID_MODULE(data, LYS_IN_YANG, NULL, LY_ENOTFOUND);
CHECK_LOG_CTX("Augment extension target node \"/a:n1\" from module \"b\" was not found.",
- "/b:{extension='sx:augment-structure'}/{augment='/a:n1'}");
+ "Path \"/b:{extension='sx:augment-structure'}/{augment='/a:n1'}\".");
}
static void
diff --git a/tests/utests/extensions/test_yangdata.c b/tests/utests/extensions/test_yangdata.c
index 8c0176f..57caaf2 100644
--- a/tests/utests/extensions/test_yangdata.c
+++ b/tests/utests/extensions/test_yangdata.c
@@ -119,7 +119,7 @@ test_schema(void **state)
assert_null(mod->compiled->exts);
CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": "
"Extension rc:yang-data is ignored since it appears as a non top-level statement in \"container\" statement.",
- "/b:b/{extension='rc:yang-data'}/template");
+ "Path \"/b:b/{extension='rc:yang-data'}/template\".");
assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0));
assert_string_equal(printed, info);
free(printed);
@@ -168,7 +168,7 @@ test_schema_invalid(void **state)
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Invalid keyword \"leaf\" as a child of \"rc:yang-data template\" extension instance.",
- "/a:{extension='rc:yang-data'}/template");
+ "Path \"/a:{extension='rc:yang-data'}/template\".");
data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
@@ -177,7 +177,7 @@ test_schema_invalid(void **state)
CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": "
"Extension rc:yang-data is instantiated with leaf top level data node (inside a choice), "
"but only a single container data node is allowed.",
- "/a:{extension='rc:yang-data'}/template");
+ "Path \"/a:{extension='rc:yang-data'}/template\".");
data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
@@ -186,7 +186,7 @@ test_schema_invalid(void **state)
CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": "
"Extension rc:yang-data is instantiated with multiple top level data nodes (inside a single choice's case), "
"but only a single container data node is allowed.",
- "/a:{extension='rc:yang-data'}/template");
+ "Path \"/a:{extension='rc:yang-data'}/template\".");
data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
@@ -195,7 +195,7 @@ test_schema_invalid(void **state)
CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": "
"Extension rc:yang-data is instantiated with multiple top level data nodes, "
"but only a single container data node is allowed.",
- "/a:{extension='rc:yang-data'}/template");
+ "Path \"/a:{extension='rc:yang-data'}/template\".");
data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
@@ -204,14 +204,14 @@ test_schema_invalid(void **state)
CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": "
"Extension rc:yang-data is instantiated without any top level data node, "
"but exactly one container data node is expected.",
- "/a:{extension='rc:yang-data'}/template");
+ "Path \"/a:{extension='rc:yang-data'}/template\".");
data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
"rc:yang-data { container x { leaf x {type string;}}}}";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Extension instance \"rc:yang-data\" missing argument element \"name\".", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Extension instance \"rc:yang-data\" missing argument element \"name\".", NULL);
data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
@@ -220,7 +220,7 @@ test_schema_invalid(void **state)
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, data, LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": "
"Extension rc:yang-data is instantiated multiple times.",
- "/a:{extension='rc:yang-data'}/template");
+ "Path \"/a:{extension='rc:yang-data'}/template\".");
data = "module a {yang-version 1.1; namespace urn:tests:extensions:yangdata:a; prefix self;"
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
@@ -230,7 +230,7 @@ test_schema_invalid(void **state)
CHECK_LOG_CTX("Ext plugin \"ly2 yang-data v1\": "
"Extension rc:yang-data is instantiated with leaf-list top level data node, "
"but only a single container data node is allowed.",
- "/a:{extension='rc:yang-data'}/template");
+ "Path \"/a:{extension='rc:yang-data'}/template\".");
}
static void
diff --git a/tests/utests/node/list.c b/tests/utests/node/list.c
index 8b14ece..987b416 100644
--- a/tests/utests/node/list.c
+++ b/tests/utests/node/list.c
@@ -169,8 +169,8 @@ test_schema_yang(void **state)
"leaf group{type string;}"
"}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_0\" failed.", NULL,
- "Invalid value \"-1\" of \"max-elements\".", "Line number 5.");
+ CHECK_LOG_CTX("Parsing module \"TERR_0\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid value \"-1\" of \"max-elements\".", "Line number 5.");
schema = MODULE_CREATE_YANG("TERR_0", "list user {"
"key uid;"
@@ -181,8 +181,8 @@ test_schema_yang(void **state)
"leaf group{type string;}"
"}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_0\" failed.", NULL,
- "Value \"4294967298\" is out of \"max-elements\" bounds.", "Line number 5.");
+ CHECK_LOG_CTX("Parsing module \"TERR_0\" failed.", NULL);
+ CHECK_LOG_CTX("Value \"4294967298\" is out of \"max-elements\" bounds.", "Line number 5.");
schema = MODULE_CREATE_YANG("TERR_0", "list user {"
"key uid;"
@@ -193,7 +193,7 @@ test_schema_yang(void **state)
"leaf group{type string;}"
"}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("List min-elements 20 is bigger than max-elements 10.", "/TERR_0:user");
+ CHECK_LOG_CTX("List min-elements 20 is bigger than max-elements 10.", "Path \"/TERR_0:user\".");
schema = MODULE_CREATE_YANG("TERR_0", "list user {"
"key uid;"
@@ -204,8 +204,8 @@ test_schema_yang(void **state)
"leaf group{type string;}"
"}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_0\" failed.", NULL,
- "Invalid value \"-1\" of \"min-elements\".", "Line number 5.");
+ CHECK_LOG_CTX("Parsing module \"TERR_0\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid value \"-1\" of \"min-elements\".", "Line number 5.");
schema = MODULE_CREATE_YANG("TERR_0", "list user {"
"key uid;"
@@ -215,8 +215,8 @@ test_schema_yang(void **state)
"leaf group{type string;}"
"}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_0\" failed.", NULL,
- "Duplicate keyword \"key\".", "Line number 5.");
+ CHECK_LOG_CTX("Parsing module \"TERR_0\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate keyword \"key\".", "Line number 5.");
schema = MODULE_CREATE_YANG("T6", "list user {"
"config false;"
@@ -282,8 +282,8 @@ test_schema_yang(void **state)
"leaf group{type string;}"
"}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERROR0\" failed.", NULL,
- "Invalid value \"systeme\" of \"ordered-by\".", "Line number 5.");
+ CHECK_LOG_CTX("Parsing module \"TERROR0\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid value \"systeme\" of \"ordered-by\".", "Line number 5.");
schema = MODULE_CREATE_YANG("TERROR0", "list \"\" {"
"key uid;"
@@ -294,8 +294,8 @@ test_schema_yang(void **state)
"leaf group{type string;}"
"}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERROR0\" failed.", NULL,
- "Statement argument is required.", "Line number 5.");
+ CHECK_LOG_CTX("Parsing module \"TERROR0\" failed.", NULL);
+ CHECK_LOG_CTX("Statement argument is required.", "Line number 5.");
schema = MODULE_CREATE_YANG("T9", "list user {"
"key uid;"
@@ -389,7 +389,7 @@ test_schema_yin(void **state)
" <leaf name=\"group\"><type name=\"string\"/></leaf>"
"</list>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
- CHECK_LOG_CTX("The list's key \"u<id\" not found.", "/T00:user");
+ CHECK_LOG_CTX("The list's key \"u<id\" not found.", "Path \"/T00:user\".");
schema = MODULE_CREATE_YIN("T1", "<list name=\"user\"> "
" <key value=\"uid\"/>"
@@ -498,8 +498,8 @@ test_schema_yin(void **state)
" <leaf name=\"uid\"> <type name=\"int32\"> </leaf>"
"</list>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_0\" failed.", NULL,
- "Invalid value \"-1\" of \"value\" attribute in \"max-elements\" element.", "Line number 8.");
+ CHECK_LOG_CTX("Parsing module \"TERR_0\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid value \"-1\" of \"value\" attribute in \"max-elements\" element.", "Line number 8.");
schema = MODULE_CREATE_YIN("TERR_0",
"<list name=\"user\">"
@@ -511,8 +511,8 @@ test_schema_yin(void **state)
" <leaf name=\"group\"> <type name=\"string\"/> </leaf>"
"</list>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_0\" failed.", NULL,
- "Value \"4294967298\" of \"value\" attribute in \"max-elements\" element is out of bounds.", "Line number 8.");
+ CHECK_LOG_CTX("Parsing module \"TERR_0\" failed.", NULL);
+ CHECK_LOG_CTX("Value \"4294967298\" of \"value\" attribute in \"max-elements\" element is out of bounds.", "Line number 8.");
schema = MODULE_CREATE_YIN("TERR_0",
"<list name=\"user\">"
@@ -524,8 +524,9 @@ test_schema_yin(void **state)
" <leaf name=\"group\"> <type name=\"string\"/> </leaf>"
"</list>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_0\" failed.", NULL,
- "Invalid combination of min-elements and max-elements: min value 20 is bigger than the max value 10.", "Line number 8.");
+ CHECK_LOG_CTX("Parsing module \"TERR_0\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid combination of min-elements and max-elements: min value 20 is bigger than the max value 10.",
+ "Line number 8.");
schema = MODULE_CREATE_YIN("TERR_0",
"<list name=\"user\">"
@@ -537,8 +538,8 @@ test_schema_yin(void **state)
" <leaf name=\"group\"> <type name=\"string\"/> </leaf>"
"</list>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_0\" failed.", NULL,
- "Value \"-1\" of \"value\" attribute in \"min-elements\" element is out of bounds.", "Line number 8.");
+ CHECK_LOG_CTX("Parsing module \"TERR_0\" failed.", NULL);
+ CHECK_LOG_CTX("Value \"-1\" of \"value\" attribute in \"min-elements\" element is out of bounds.", "Line number 8.");
schema = MODULE_CREATE_YIN("TERR_0",
"<list name=\"user\">"
@@ -549,8 +550,8 @@ test_schema_yin(void **state)
" <leaf name=\"group\"> <type name=\"string\"/> </leaf>"
"</list>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_0\" failed.", NULL,
- "Redefinition of \"key\" sub-element in \"list\" element.", "Line number 8.");
+ CHECK_LOG_CTX("Parsing module \"TERR_0\" failed.", NULL);
+ CHECK_LOG_CTX("Redefinition of \"key\" sub-element in \"list\" element.", "Line number 8.");
schema = MODULE_CREATE_YIN("T6",
"<list name=\"user\">"
@@ -620,8 +621,8 @@ test_schema_yin(void **state)
" <leaf name=\"group\"><type name=\"string\"/> </leaf>"
"</list>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERROR0\" failed.", NULL,
- "Invalid value \"systeme\" of \"value\" attribute in \"ordered-by\" element. Valid values are \"system\" and \"user\".",
+ CHECK_LOG_CTX("Parsing module \"TERROR0\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid value \"systeme\" of \"value\" attribute in \"ordered-by\" element. Valid values are \"system\" and \"user\".",
"Line number 8.");
schema = MODULE_CREATE_YIN("T_DEFS1",
diff --git a/tests/utests/schema/test_printer_tree.c b/tests/utests/schema/test_printer_tree.c
index c076ece..40fb15f 100644
--- a/tests/utests/schema/test_printer_tree.c
+++ b/tests/utests/schema/test_printer_tree.c
@@ -1574,6 +1574,7 @@ print_compiled_node(void **state)
" yang-version 1.1;\n"
" namespace \"x:y\";\n"
" prefix x;\n"
+ "\n"
" container g {\n"
" leaf a {\n"
" type string;\n"
@@ -1586,6 +1587,12 @@ print_compiled_node(void **state)
" leaf c {\n"
" type string;\n"
" }\n"
+ " list l {\n"
+ " key \"ip\";\n"
+ " leaf ip {\n"
+ " type string;\n"
+ " }\n"
+ " }\n"
" }\n"
" }\n"
"}\n";
@@ -1610,13 +1617,31 @@ print_compiled_node(void **state)
ly_out_reset(UTEST_OUT);
+ /* pyang -f tree --tree-path /g/h/l */
+ expect =
+ "module: a26\n"
+ " +--rw g\n"
+ " +--rw h\n"
+ " +--rw l* [ip]\n"
+ " +--rw ip string\n";
+
+ node = lys_find_path(UTEST_LYCTX, NULL, "/a26:g/h/l", 0);
+ CHECK_POINTER(node, 1);
+ assert_int_equal(LY_SUCCESS, lys_print_node(UTEST_OUT, node, LYS_OUT_TREE, 72, 0));
+ assert_int_equal(strlen(expect), ly_out_printed(UTEST_OUT));
+ assert_string_equal(printed, expect);
+
+ ly_out_reset(UTEST_OUT);
+
/* pyang -f tree --tree-path /g/h */
expect =
"module: a26\n"
" +--rw g\n"
" +--rw h\n"
" +--rw b string\n"
- " +--rw c? string\n";
+ " +--rw c? string\n"
+ " +--rw l* [ip]\n"
+ " +--rw ip string\n";
node = lys_find_path(UTEST_LYCTX, NULL, "/a26:g/h", 0);
CHECK_POINTER(node, 1);
@@ -1643,6 +1668,59 @@ print_compiled_node(void **state)
TEST_LOCAL_TEARDOWN;
}
+static void
+print_compiled_node_augment(void **state)
+{
+ TEST_LOCAL_SETUP;
+ const struct lysc_node *node;
+
+ orig =
+ "module b26xx {\n"
+ " yang-version 1.1;\n"
+ " namespace \"xx:y\";\n"
+ " prefix xx;\n"
+ " container c;\n"
+ "}\n";
+
+ UTEST_ADD_MODULE(orig, LYS_IN_YANG, NULL, &mod);
+
+ /* module with import statement */
+ orig =
+ "module b26 {\n"
+ " yang-version 1.1;\n"
+ " namespace \"x:y\";\n"
+ " prefix x;\n"
+ "\n"
+ " import b26xx {\n"
+ " prefix xx;\n"
+ " }\n"
+ "\n"
+ " augment \"/xx:c\" {\n"
+ " container e;\n"
+ " }\n"
+ "}\n";
+
+ UTEST_ADD_MODULE(orig, LYS_IN_YANG, NULL, &mod);
+
+ /* pyang -f tree --tree-path /c/e ... but prefixes modified */
+ expect =
+ "module: b26\n"
+ " +--rw xx:c\n"
+ " +--rw e\n";
+
+ /* using lysc tree */
+ ly_ctx_set_options(UTEST_LYCTX, LY_CTX_SET_PRIV_PARSED);
+ node = lys_find_path(UTEST_LYCTX, NULL, "/b26xx:c/b26:e", 0);
+ CHECK_POINTER(node, 1);
+ assert_int_equal(LY_SUCCESS, lys_print_node(UTEST_OUT, node, LYS_OUT_TREE, 72, 0));
+ assert_int_equal(strlen(expect), ly_out_printed(UTEST_OUT));
+ assert_string_equal(printed, expect);
+ ly_out_reset(UTEST_OUT);
+ ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_SET_PRIV_PARSED);
+
+ TEST_LOCAL_TEARDOWN;
+}
+
static LY_ERR
local_imp_clb(const char *UNUSED(mod_name), const char *UNUSED(mod_rev), const char *UNUSED(submod_name),
const char *UNUSED(sub_rev), void *user_data, LYS_INFORMAT *format,
@@ -2365,6 +2443,43 @@ structure(void **state)
TEST_LOCAL_TEARDOWN;
}
+static void
+annotation(void **state)
+{
+ TEST_LOCAL_SETUP;
+
+ orig =
+ "module ann {\n"
+ " yang-version 1.1;\n"
+ " namespace \"urn:example:ann\";\n"
+ " prefix an;\n"
+ "\n"
+ " import ietf-yang-metadata {\n"
+ " prefix md;\n"
+ " }\n"
+ "\n"
+ " leaf lf1 {\n"
+ " type string;\n"
+ " }\n"
+ " md:annotation avalue {\n"
+ " type string;\n"
+ " }\n"
+ "}\n";
+
+ expect =
+ "module: ann\n"
+ " +--rw lf1? string\n";
+
+ /* annotation is ignored without error message */
+ UTEST_ADD_MODULE(orig, LYS_IN_YANG, NULL, &mod);
+ TEST_LOCAL_PRINT(mod, 72);
+ assert_int_equal(strlen(expect), ly_out_printed(UTEST_OUT));
+ assert_string_equal(printed, expect);
+ ly_out_reset(UTEST_OUT);
+
+ TEST_LOCAL_TEARDOWN;
+}
+
int
main(void)
{
@@ -2395,10 +2510,12 @@ main(void)
UTEST(transition_between_rpc_and_notif),
UTEST(local_augment),
UTEST(print_compiled_node),
+ UTEST(print_compiled_node_augment),
UTEST(print_parsed_submodule),
UTEST(yang_data),
UTEST(mount_point),
UTEST(structure),
+ UTEST(annotation),
};
return cmocka_run_group_tests(tests, NULL, NULL);
diff --git a/tests/utests/schema/test_schema.c b/tests/utests/schema/test_schema.c
index 175b569..17c4e4f 100644
--- a/tests/utests/schema/test_schema.c
+++ b/tests/utests/schema/test_schema.c
@@ -91,7 +91,8 @@ test_imp_clb(const char *UNUSED(mod_name), const char *UNUSED(mod_rev), const ch
const char *test_str__; \
TEST_SCHEMA_STR(RFC7950, YIN, MOD_NAME, CONTENT, test_str__) \
assert_int_not_equal(lys_parse_mem(UTEST_LYCTX, test_str__, YIN ? LYS_IN_YIN : LYS_IN_YANG, NULL), LY_SUCCESS); \
- CHECK_LOG_CTX("Parsing module \""MOD_NAME"\" failed.", NULL, ERRMSG, ERRPATH); \
+ CHECK_LOG_CTX("Parsing module \""MOD_NAME"\" failed.", NULL); \
+ CHECK_LOG_CTX(ERRMSG, ERRPATH); \
}
#define TEST_STMT_DUP(RFC7950, YIN, STMT, MEMBER, VALUE1, VALUE2, LINE) \
@@ -283,12 +284,12 @@ test_revisions(void **state)
strcpy(rev->date, "2018-12-31");
assert_int_equal(2, LY_ARRAY_COUNT(revs));
- assert_string_equal("2018-01-01", &revs[0]);
- assert_string_equal("2018-12-31", &revs[1]);
+ assert_string_equal("2018-01-01", revs[0].date);
+ assert_string_equal("2018-12-31", revs[1].date);
/* the order should be fixed, so the newest revision will be the first in the array */
lysp_sort_revisions(revs);
- assert_string_equal("2018-12-31", &revs[0]);
- assert_string_equal("2018-01-01", &revs[1]);
+ assert_string_equal("2018-12-31", revs[0].date);
+ assert_string_equal("2018-01-01", revs[1].date);
LY_ARRAY_FREE(revs);
}
@@ -306,80 +307,80 @@ test_collision_typedef(void **state)
/* collision with a built-in type */
str = "module a {namespace urn:a; prefix a; typedef binary {type string;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"binary\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"binary\" of typedef statement - name collision with a built-in type.", NULL);
str = "module a {namespace urn:a; prefix a; typedef bits {type string;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"bits\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"bits\" of typedef statement - name collision with a built-in type.", NULL);
str = "module a {namespace urn:a; prefix a; typedef boolean {type string;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"boolean\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"boolean\" of typedef statement - name collision with a built-in type.", NULL);
str = "module a {namespace urn:a; prefix a; typedef decimal64 {type string;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"decimal64\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"decimal64\" of typedef statement - name collision with a built-in type.", NULL);
str = "module a {namespace urn:a; prefix a; typedef empty {type string;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"empty\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"empty\" of typedef statement - name collision with a built-in type.", NULL);
str = "module a {namespace urn:a; prefix a; typedef enumeration {type string;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"enumeration\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"enumeration\" of typedef statement - name collision with a built-in type.", NULL);
str = "module a {namespace urn:a; prefix a; typedef int8 {type string;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"int8\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"int8\" of typedef statement - name collision with a built-in type.", NULL);
str = "module a {namespace urn:a; prefix a; typedef int16 {type string;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"int16\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"int16\" of typedef statement - name collision with a built-in type.", NULL);
str = "module a {namespace urn:a; prefix a; typedef int32 {type string;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"int32\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"int32\" of typedef statement - name collision with a built-in type.", NULL);
str = "module a {namespace urn:a; prefix a; typedef int64 {type string;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"int64\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"int64\" of typedef statement - name collision with a built-in type.", NULL);
str = "module a {namespace urn:a; prefix a; typedef instance-identifier {type string;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"instance-identifier\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"instance-identifier\" of typedef statement - name collision with a built-in type.", NULL);
str = "module a {namespace urn:a; prefix a; typedef identityref {type string;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"identityref\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"identityref\" of typedef statement - name collision with a built-in type.", NULL);
str = "module a {namespace urn:a; prefix a; typedef leafref {type string;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"leafref\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"leafref\" of typedef statement - name collision with a built-in type.", NULL);
str = "module a {namespace urn:a; prefix a; typedef string {type int8;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"string\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"string\" of typedef statement - name collision with a built-in type.", NULL);
str = "module a {namespace urn:a; prefix a; typedef union {type string;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"union\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"union\" of typedef statement - name collision with a built-in type.", NULL);
str = "module a {namespace urn:a; prefix a; typedef uint8 {type string;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"uint8\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"uint8\" of typedef statement - name collision with a built-in type.", NULL);
str = "module a {namespace urn:a; prefix a; typedef uint16 {type string;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"uint16\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"uint16\" of typedef statement - name collision with a built-in type.", NULL);
str = "module a {namespace urn:a; prefix a; typedef uint32 {type string;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"uint32\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"uint32\" of typedef statement - name collision with a built-in type.", NULL);
str = "module a {namespace urn:a; prefix a; typedef uint64 {type string;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"uint64\" of typedef statement - name collision with a built-in type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"uint64\" of typedef statement - name collision with a built-in type.", NULL);
str = "module mytypes {namespace urn:types; prefix t; typedef binary_ {type string;} typedef bits_ {type string;} typedef boolean_ {type string;} "
"typedef decimal64_ {type string;} typedef empty_ {type string;} typedef enumeration_ {type string;} typedef int8_ {type string;} typedef int16_ {type string;}"
@@ -391,34 +392,34 @@ test_collision_typedef(void **state)
/* collision in node's scope */
str = "module a {namespace urn:a; prefix a; container c {typedef y {type int8;} typedef y {type string;}}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"y\" of typedef statement - name collision with sibling type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"y\" of typedef statement - name collision with sibling type.", NULL);
/* collision with parent node */
str = "module a {namespace urn:a; prefix a; container c {container d {typedef y {type int8;}} typedef y {type string;}}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"y\" of typedef statement - name collision with another scoped type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"y\" of typedef statement - name collision with another scoped type.", NULL);
/* collision with module's top-level */
str = "module a {namespace urn:a; prefix a; typedef x {type string;} container c {typedef x {type int8;}}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"x\" of typedef statement - scoped type collide with a top-level type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"x\" of typedef statement - scoped type collide with a top-level type.", NULL);
/* collision of submodule's node with module's top-level */
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule b {belongs-to a {prefix a;} container c {typedef x {type string;}}}");
str = "module a {namespace urn:a; prefix a; include b; typedef x {type int8;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"x\" of typedef statement - scoped type collide with a top-level type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"x\" of typedef statement - scoped type collide with a top-level type.", NULL);
/* collision of module's node with submodule's top-level */
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule b {belongs-to a {prefix a;} typedef x {type int8;}}");
str = "module a {namespace urn:a; prefix a; include b; container c {typedef x {type string;}}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"x\" of typedef statement - scoped type collide with a top-level type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"x\" of typedef statement - scoped type collide with a top-level type.", NULL);
/* collision of submodule's node with another submodule's top-level */
str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub; include bsub;}";
@@ -426,29 +427,29 @@ test_collision_typedef(void **state)
list[1].data = "submodule bsub {belongs-to a {prefix a;} container c {typedef g {type int;}}}";
ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list);
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"g\" of typedef statement - scoped type collide with a top-level type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"g\" of typedef statement - scoped type collide with a top-level type.", NULL);
/* collision of module's top-levels */
str = "module a {namespace urn:a; prefix a; typedef test {type string;} typedef test {type int8;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"test\" of typedef statement - name collision with another top-level type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"test\" of typedef statement - name collision with another top-level type.", NULL);
/* collision of submodule's top-levels */
submod = "submodule asub {belongs-to a {prefix a;} typedef g {type int;} typedef g {type int;}}";
str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub;}";
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, submod);
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"g\" of typedef statement - name collision with another top-level type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"g\" of typedef statement - name collision with another top-level type.", NULL);
/* collision of module's top-level with submodule's top-levels */
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule b {belongs-to a {prefix a;} typedef x {type string;}}");
str = "module a {namespace urn:a; prefix a; include b; typedef x {type int8;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"x\" of typedef statement - name collision with another top-level type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"x\" of typedef statement - name collision with another top-level type.", NULL);
/* collision of submodule's top-level with another submodule's top-levels */
str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub; include bsub;}";
@@ -456,15 +457,14 @@ test_collision_typedef(void **state)
list[1].data = "submodule bsub {belongs-to a {prefix a;} typedef g {type int;}}";
ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list);
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"g\" of typedef statement - name collision with another top-level type.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"g\" of typedef statement - name collision with another top-level type.", NULL);
/* error in type-stmt */
str = "module a {namespace urn:a; prefix a; container c {typedef x {type t{}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Unexpected end-of-input.", "Line number 1.");
- UTEST_LOG_CLEAN;
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Unexpected end-of-input.", "Line number 1.");
/* no collision if the same names are in different scope */
str = "module a {yang-version 1.1; namespace urn:a; prefix a;"
@@ -485,34 +485,34 @@ test_collision_grouping(void **state)
/* collision in node's scope */
str = "module a {namespace urn:a; prefix a; container c {grouping y; grouping y;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"y\" of grouping statement - name collision with sibling grouping.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"y\" of grouping statement - name collision with sibling grouping.", NULL);
/* collision with parent node */
str = "module a {namespace urn:a; prefix a; container c {container d {grouping y;} grouping y;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"y\" of grouping statement - name collision with another scoped grouping.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"y\" of grouping statement - name collision with another scoped grouping.", NULL);
/* collision with module's top-level */
str = "module a {namespace urn:a; prefix a; grouping x; container c {grouping x;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"x\" of grouping statement - scoped grouping collide with a top-level grouping.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"x\" of grouping statement - scoped grouping collide with a top-level grouping.", NULL);
/* collision of submodule's node with module's top-level */
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule b {belongs-to a {prefix a;} container c {grouping x;}}");
str = "module a {namespace urn:a; prefix a; include b; grouping x;}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"x\" of grouping statement - scoped grouping collide with a top-level grouping.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"x\" of grouping statement - scoped grouping collide with a top-level grouping.", NULL);
/* collision of module's node with submodule's top-level */
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule b {belongs-to a {prefix a;} grouping x;}");
str = "module a {namespace urn:a; prefix a; include b; container c {grouping x;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"x\" of grouping statement - scoped grouping collide with a top-level grouping.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"x\" of grouping statement - scoped grouping collide with a top-level grouping.", NULL);
/* collision of submodule's node with another submodule's top-level */
str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub; include bsub;}";
@@ -520,29 +520,29 @@ test_collision_grouping(void **state)
list[1].data = "submodule bsub {belongs-to a {prefix a;} container c {grouping g;}}";
ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list);
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"g\" of grouping statement - scoped grouping collide with a top-level grouping.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"g\" of grouping statement - scoped grouping collide with a top-level grouping.", NULL);
/* collision of module's top-levels */
str = "module a {namespace urn:a; prefix a; grouping test; grouping test;}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"test\" of grouping statement - name collision with another top-level grouping.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"test\" of grouping statement - name collision with another top-level grouping.", NULL);
/* collision of submodule's top-levels */
submod = "submodule asub {belongs-to a {prefix a;} grouping g; grouping g;}";
str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub;}";
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, submod);
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"g\" of grouping statement - name collision with another top-level grouping.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"g\" of grouping statement - name collision with another top-level grouping.", NULL);
/* collision of module's top-level with submodule's top-levels */
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule b {belongs-to a {prefix a;} grouping x;}");
str = "module a {namespace urn:a; prefix a; include b; grouping x;}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"x\" of grouping statement - name collision with another top-level grouping.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"x\" of grouping statement - name collision with another top-level grouping.", NULL);
/* collision of submodule's top-level with another submodule's top-levels */
str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub; include bsub;}";
@@ -550,25 +550,27 @@ test_collision_grouping(void **state)
list[1].data = "submodule bsub {belongs-to a {prefix a;} grouping g;}";
ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list);
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"g\" of grouping statement - name collision with another top-level grouping.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"g\" of grouping statement - name collision with another top-level grouping.", NULL);
/* collision in nested groupings, top-level */
str = "module a {namespace urn:a; prefix a; grouping g {grouping g;}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"g\" of grouping statement - scoped grouping collide with a top-level grouping.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"g\" of grouping statement - scoped grouping collide with a top-level grouping.", NULL);
/* collision in nested groupings, in node */
str = "module a {namespace urn:a; prefix a; container c {grouping g {grouping g;}}}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"g\" of grouping statement - name collision with another scoped grouping.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"g\" of grouping statement - name collision with another scoped grouping.", NULL);
/* no collision if the same names are in different scope */
str = "module a {yang-version 1.1; namespace urn:a; prefix a;"
"container c {grouping g;} container d {grouping g;}}";
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
+ CHECK_LOG_CTX("Locally scoped grouping \"g\" not used.", NULL);
+ CHECK_LOG_CTX("Locally scoped grouping \"g\" not used.", NULL);
}
static void
@@ -584,24 +586,24 @@ test_collision_identity(void **state)
/* collision of module's top-levels */
str = "module a {yang-version 1.1; namespace urn:a; prefix a; identity g; identity g;}";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"g\" of identity statement - name collision with another top-level identity.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"g\" of identity statement - name collision with another top-level identity.", NULL);
/* collision of submodule's top-levels */
submod = "submodule asub {belongs-to a {prefix a;} identity g; identity g;}";
str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub;}";
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, submod);
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"g\" of identity statement - name collision with another top-level identity.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"g\" of identity statement - name collision with another top-level identity.", NULL);
/* collision of module's top-level with submodule's top-levels */
submod = "submodule asub {belongs-to a {prefix a;} identity g;}";
str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub; identity g;}";
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, submod);
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"g\" of identity statement - name collision with another top-level identity.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"g\" of identity statement - name collision with another top-level identity.", NULL);
/* collision of submodule's top-level with another submodule's top-levels */
str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub; include bsub;}";
@@ -609,8 +611,8 @@ test_collision_identity(void **state)
list[1].data = "submodule bsub {belongs-to a {prefix a;} identity g;}";
ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list);
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"g\" of identity statement - name collision with another top-level identity.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"g\" of identity statement - name collision with another top-level identity.", NULL);
}
static void
@@ -626,24 +628,24 @@ test_collision_feature(void **state)
/* collision of module's top-levels */
str = "module a {yang-version 1.1; namespace urn:a; prefix a; feature g; feature g;}";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"g\" of feature statement - name collision with another top-level feature.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"g\" of feature statement - name collision with another top-level feature.", NULL);
/* collision of submodule's top-levels */
submod = "submodule asub {belongs-to a {prefix a;} feature g; feature g;}";
str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub;}";
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, submod);
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"g\" of feature statement - name collision with another top-level feature.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"g\" of feature statement - name collision with another top-level feature.", NULL);
/* collision of module's top-level with submodule's top-levels */
submod = "submodule asub {belongs-to a {prefix a;} feature g;}";
str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub; feature g;}";
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, submod);
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"g\" of feature statement - name collision with another top-level feature.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"g\" of feature statement - name collision with another top-level feature.", NULL);
/* collision of submodule's top-level with another submodule's top-levels */
str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub; include bsub;}";
@@ -651,8 +653,8 @@ test_collision_feature(void **state)
list[1].data = "submodule bsub {belongs-to a {prefix a;} feature g;}";
ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list);
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
- "Duplicate identifier \"g\" of feature statement - name collision with another top-level feature.", NULL);
+ CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"g\" of feature statement - name collision with another top-level feature.", NULL);
}
static void
@@ -1046,15 +1048,15 @@ test_includes(void **state)
ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list);
mod = ly_ctx_load_module(UTEST_LYCTX, "main_b", NULL, NULL);
assert_null(mod);
- CHECK_LOG_CTX("Loading \"main_b\" module failed.", NULL,
- "Data model \"main_b\" not found in local searchdirs.", NULL,
- "Parsing module \"main_b\" failed.", NULL,
- "Including \"sub_b_one\" submodule into \"main_b\" failed.", NULL,
- "Data model \"sub_b_one\" not found in local searchdirs.", NULL,
- "Parsing submodule \"sub_b_one\" failed.", NULL,
- "YANG 1.1 requires all submodules to be included from main module. But submodule \"sub_b_one\" includes "
- "submodule \"sub_b_two\" which is not included by main module \"main_b\".", NULL,
- "YANG version 1.1 expects all includes in main module, includes in submodules (sub_b_one) are not necessary.", NULL);
+ CHECK_LOG_CTX("Loading \"main_b\" module failed.", NULL);
+ CHECK_LOG_CTX("Data model \"main_b\" not found in local searchdirs.", NULL);
+ CHECK_LOG_CTX("Parsing module \"main_b\" failed.", NULL);
+ CHECK_LOG_CTX("Including \"sub_b_one\" submodule into \"main_b\" failed.", NULL);
+ CHECK_LOG_CTX("Data model \"sub_b_one\" not found in local searchdirs.", NULL);
+ CHECK_LOG_CTX("Parsing submodule \"sub_b_one\" failed.", NULL);
+ CHECK_LOG_CTX("YANG 1.1 requires all submodules to be included from main module. But submodule \"sub_b_one\" includes "
+ "submodule \"sub_b_two\" which is not included by main module \"main_b\".", NULL);
+ CHECK_LOG_CTX("YANG version 1.1 expects all includes in main module, includes in submodules (sub_b_one) are not necessary.", NULL);
}
{
@@ -1073,6 +1075,7 @@ test_includes(void **state)
assert_false(mod->parsed->includes[1].injected);
/* result is ok, but log includes the warning */
CHECK_LOG_CTX("YANG version 1.1 expects all includes in main module, includes in submodules (sub_c_two) are not necessary.", NULL);
+ CHECK_LOG_CTX("YANG version 1.1 expects all includes in main module, includes in submodules (sub_c_one) are not necessary.", NULL);
}
}
@@ -1083,7 +1086,8 @@ test_key_order(void **state)
const struct lysc_node *node;
struct module_clb_list list1[] = {
- {"a", "module a {"
+ {
+ "a", "module a {"
"yang-version 1.1;"
"namespace urn:test:a;"
"prefix a;"
@@ -1092,7 +1096,8 @@ test_key_order(void **state)
" leaf k2 {type string;}"
" leaf k1 {type string;}"
"}"
- "}"},
+ "}"
+ },
{NULL, NULL}
};
@@ -1106,7 +1111,8 @@ test_key_order(void **state)
assert_string_equal("k2", node->name);
struct module_clb_list list2[] = {
- {"b", "module b {"
+ {
+ "b", "module b {"
"yang-version 1.1;"
"namespace urn:test:b;"
"prefix b;"
@@ -1121,7 +1127,8 @@ test_key_order(void **state)
" leaf k1 {type string;}"
" leaf k3 {type string;}"
"}"
- "}"},
+ "}"
+ },
{NULL, NULL}
};
@@ -1156,7 +1163,7 @@ test_disabled_enum(void **state)
"}}"
"}";
assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Enumeration type of node \"l\" without any (or all disabled) valid values.", "Schema location \"/a:l\".");
+ CHECK_LOG_CTX("Node \"l\" without any (or all disabled) valid values.", "Schema location \"/a:l\".");
/* disabled default value */
str = "module a {"
@@ -1263,10 +1270,10 @@ test_identity(void **state)
assert_ptr_equal(mod->identities[1].derived[0], &mod->identities[0]);
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule inv_sub {belongs-to inv {prefix inv;} identity i1;}");
- TEST_SCHEMA_ERR(0, 0, "inv", "identity i1 {base i2;}", "Unable to find base (i2) of identity \"i1\".", "/inv:{identity='i1'}");
- TEST_SCHEMA_ERR(0, 0, "inv", "identity i1 {base i1;}", "Identity \"i1\" is derived from itself.", "/inv:{identity='i1'}");
+ TEST_SCHEMA_ERR(0, 0, "inv", "identity i1 {base i2;}", "Unable to find base (i2) of identity \"i1\".", "Path \"/inv:{identity='i1'}\".");
+ TEST_SCHEMA_ERR(0, 0, "inv", "identity i1 {base i1;}", "Identity \"i1\" is derived from itself.", "Path \"/inv:{identity='i1'}\".");
TEST_SCHEMA_ERR(0, 0, "inv", "identity i1 {base i2;}identity i2 {base i3;}identity i3 {base i1;}",
- "Identity \"i1\" is indirectly derived from itself.", "/inv:{identity='i3'}");
+ "Identity \"i1\" is indirectly derived from itself.", "Path \"/inv:{identity='i3'}\".");
/* base in non-implemented module */
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb,
@@ -1606,8 +1613,8 @@ test_extension_argument_element(void **state)
/* invalid */
mod_test_yang = "module x { namespace \"urn:x\"; prefix x; import a { prefix a; } a:e; }";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, mod_test_yang, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"x\" failed.", NULL,
- "Extension instance \"a:e\" missing argument element \"name\".", NULL);
+ CHECK_LOG_CTX("Parsing module \"x\" failed.", NULL);
+ CHECK_LOG_CTX("Extension instance \"a:e\" missing argument element \"name\".", NULL);
mod_test_yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<module name=\"x\"\n"
@@ -1622,8 +1629,8 @@ test_extension_argument_element(void **state)
" <a:e/>\n"
"</module>\n";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, mod_test_yin, LYS_IN_YIN, NULL));
- CHECK_LOG_CTX("Parsing module \"x\" failed.", NULL,
- "Extension instance \"a:e\" missing argument element \"name\".", NULL);
+ CHECK_LOG_CTX("Parsing module \"x\" failed.", NULL);
+ CHECK_LOG_CTX("Extension instance \"a:e\" missing argument element \"name\".", NULL);
mod_test_yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<module name=\"x\"\n"
@@ -1638,8 +1645,8 @@ test_extension_argument_element(void **state)
" <a:e name=\"xxx\"/>\n"
"</module>\n";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, mod_test_yin, LYS_IN_YIN, NULL));
- CHECK_LOG_CTX("Parsing module \"x\" failed.", NULL,
- "Extension instance \"a:e\" missing argument element \"name\".", NULL);
+ CHECK_LOG_CTX("Parsing module \"x\" failed.", NULL);
+ CHECK_LOG_CTX("Extension instance \"a:e\" missing argument element \"name\".", NULL);
mod_test_yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<module name=\"x\"\n"
@@ -1656,8 +1663,8 @@ test_extension_argument_element(void **state)
" </a:e>\n"
"</module>\n";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, mod_test_yin, LYS_IN_YIN, NULL));
- CHECK_LOG_CTX("Parsing module \"x\" failed.", NULL,
- "Extension instance \"a:e\" element and its argument element \"name\" are expected in the same namespace, but they differ.",
+ CHECK_LOG_CTX("Parsing module \"x\" failed.", NULL);
+ CHECK_LOG_CTX("Extension instance \"a:e\" element and its argument element \"name\" are expected in the same namespace, but they differ.",
NULL);
mod_test_yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
@@ -1675,8 +1682,8 @@ test_extension_argument_element(void **state)
" </a:e>\n"
"</module>\n";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, mod_test_yin, LYS_IN_YIN, NULL));
- CHECK_LOG_CTX("Parsing module \"x\" failed.", NULL,
- "Extension instance \"a:e\" expects argument element \"name\" as its first XML child, but \"value\" element found.",
+ CHECK_LOG_CTX("Parsing module \"x\" failed.", NULL);
+ CHECK_LOG_CTX("Extension instance \"a:e\" expects argument element \"name\" as its first XML child, but \"value\" element found.",
NULL);
}
diff --git a/tests/utests/schema/test_tree_schema_compile.c b/tests/utests/schema/test_tree_schema_compile.c
index d6f0538..85da486 100644
--- a/tests/utests/schema/test_tree_schema_compile.c
+++ b/tests/utests/schema/test_tree_schema_compile.c
@@ -1,9 +1,10 @@
-/*
+/**
* @file test_tree_schema_compile.c
- * @author: Radek Krejci <rkrejci@cesnet.cz>
+ * @author Radek Krejci <rkrejci@cesnet.cz>
+ * @author Michal Vasko <mvasko@cesnet.cz>
* @brief unit tests for functions from parser_yang.c
*
- * Copyright (c) 2018 CESNET, z.s.p.o.
+ * 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.
@@ -82,6 +83,7 @@ test_module(void **state)
ly_in_free(in, 0);
assert_int_equal(0, mod->implemented);
assert_int_equal(LY_EINVAL, lys_set_implemented(mod, feats));
+ CHECK_LOG_CTX("Feature \"invalid\" not found in module \"test\".", NULL);
assert_int_equal(LY_SUCCESS, lys_set_implemented(mod, NULL));
assert_non_null(mod->compiled);
assert_string_equal("test", mod->name);
@@ -112,7 +114,7 @@ test_module(void **state)
assert_int_equal(LY_SUCCESS, ly_in_new_memory(str, &in));
assert_int_equal(LY_EEXIST, lys_parse(UTEST_LYCTX, in, LYS_IN_YANG, NULL, &mod));
ly_in_free(in, 0);
- CHECK_LOG_CTX("Duplicate identifier \"a\" of data definition/RPC/action/notification statement.", "/aa:a");
+ CHECK_LOG_CTX("Duplicate identifier \"a\" of data definition/RPC/action/notification statement.", "Path \"/aa:a\".");
}
static void
@@ -127,7 +129,7 @@ test_name_collisions(void **state)
" leaf c {type empty;}"
"}";
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, yang_data, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"c\" of data definition/RPC/action/notification statement.", "/a:c");
+ CHECK_LOG_CTX("Duplicate identifier \"c\" of data definition/RPC/action/notification statement.", "Path \"/a:c\".");
UTEST_LOG_CLEAN;
yang_data = "module a {namespace urn:a;prefix a;"
@@ -136,7 +138,7 @@ test_name_collisions(void **state)
" notification c;"
"}";
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, yang_data, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"c\" of data definition/RPC/action/notification statement.", "/a:c");
+ CHECK_LOG_CTX("Duplicate identifier \"c\" of data definition/RPC/action/notification statement.", "Path \"/a:c\".");
UTEST_LOG_CLEAN;
yang_data = "module a {namespace urn:a;prefix a;"
@@ -145,7 +147,7 @@ test_name_collisions(void **state)
" rpc c;"
"}";
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, yang_data, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"c\" of data definition/RPC/action/notification statement.", "/a:c");
+ CHECK_LOG_CTX("Duplicate identifier \"c\" of data definition/RPC/action/notification statement.", "Path \"/a:c\".");
UTEST_LOG_CLEAN;
yang_data = "module a {namespace urn:a;prefix a;"
@@ -159,7 +161,7 @@ test_name_collisions(void **state)
" }"
"}";
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, yang_data, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"c\" of data definition/RPC/action/notification statement.", "/a:ch/c/c");
+ CHECK_LOG_CTX("Duplicate identifier \"c\" of data definition/RPC/action/notification statement.", "Path \"/a:ch/c/c\".");
UTEST_LOG_CLEAN;
/* nested */
@@ -168,7 +170,7 @@ test_name_collisions(void **state)
"container a;"
"}}}";
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, yang_data, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"a\" of data definition/RPC/action/notification statement.", "/a:c/l/a");
+ CHECK_LOG_CTX("Duplicate identifier \"a\" of data definition/RPC/action/notification statement.", "Path \"/a:c/l/a\".");
UTEST_LOG_CLEAN;
yang_data = "module a {yang-version 1.1;namespace urn:a;prefix a;container c { list l {key \"k\"; leaf k {type string;}"
@@ -176,7 +178,7 @@ test_name_collisions(void **state)
"notification a;"
"}}}";
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, yang_data, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"a\" of data definition/RPC/action/notification statement.", "/a:c/l/a");
+ CHECK_LOG_CTX("Duplicate identifier \"a\" of data definition/RPC/action/notification statement.", "Path \"/a:c/l/a\".");
UTEST_LOG_CLEAN;
yang_data = "module a {yang-version 1.1;namespace urn:a;prefix a;container c { list l {key \"k\"; leaf k {type string;}"
@@ -184,7 +186,7 @@ test_name_collisions(void **state)
"action a;"
"}}}";
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, yang_data, LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"a\" of data definition/RPC/action/notification statement.", "/a:c/l/a");
+ CHECK_LOG_CTX("Duplicate identifier \"a\" of data definition/RPC/action/notification statement.", "Path \"/a:c/l/a\".");
UTEST_LOG_CLEAN;
/* grouping */
@@ -250,15 +252,6 @@ test_node_leaflist(void **state)
assert_non_null(((struct lysc_type_leafref *)type)->realtype);
assert_int_equal(LY_TYPE_INT8, ((struct lysc_type_leafref *)type)->realtype->basetype);
- /* now test for string type is in file ./tests/utests/types/string.c */
-#if 0
- assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module b {namespace urn:b;prefix b;leaf-list ll {type string;}}", LYS_IN_YANG, &mod));
- assert_non_null(mod->compiled);
- assert_non_null((ll = (struct lysc_node_leaflist *)mod->compiled->data));
- assert_int_equal(0, ll->min);
- assert_int_equal((uint32_t)-1, ll->max);
-#endif
-
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module c {yang-version 1.1;namespace urn:c;prefix c;typedef mytype {type int8;default 10;}"
"leaf-list ll1 {type mytype;default 1; default 1; config false;}"
"leaf-list ll2 {type mytype; ordered-by user;}}", LYS_IN_YANG, &mod));
@@ -304,7 +297,7 @@ test_node_leaflist(void **state)
/* invalid */
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa;leaf-list ll {type empty;}}",
LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Leaf-list of type \"empty\" is allowed only in YANG 1.1 modules.", "/aa:ll");
+ CHECK_LOG_CTX("Leaf-list of type \"empty\" is allowed only in YANG 1.1 modules.", "Path \"/aa:ll\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module bb {yang-version 1.1;namespace urn:bb;prefix bb;leaf-list ll {type empty; default x;}}", LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Invalid default - value does not fit the type (Invalid empty value length 1.).", "Schema location \"/bb:ll\".");
@@ -317,12 +310,12 @@ test_node_leaflist(void **state)
assert_int_equal(3, LY_ARRAY_COUNT(ll->dflts));
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module dd {yang-version 1.1;namespace urn:dd;prefix dd;"
"leaf-list ll {type string; default one;default two;default one;}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Configuration leaf-list has multiple defaults of the same value \"one\".", "/dd:ll");
+ CHECK_LOG_CTX("Configuration leaf-list has multiple defaults of the same value \"one\".", "Path \"/dd:ll\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ee {yang-version 1.1; namespace urn:ee;prefix ee;"
"leaf ref {type instance-identifier {require-instance true;} default \"/ee:g\";}}", LYS_IN_YANG, NULL));
CHECK_LOG_CTX("Invalid default - value does not fit the type "
- "(Invalid instance-identifier \"/ee:g\" value - semantic error.).", "Schema location \"/ee:ref\".");
+ "(Invalid instance-identifier \"/ee:g\" value - semantic error: Not found node \"g\" in path.).", "Schema location \"/ee:ref\".");
}
static void
@@ -412,11 +405,11 @@ test_node_list(void **state)
/* invalid */
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa;list l;}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Missing key in list representing configuration data.", "/aa:l");
+ CHECK_LOG_CTX("Missing key in list representing configuration data.", "Path \"/aa:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module bb {yang-version 1.1; namespace urn:bb;prefix bb;"
"list l {key x; leaf x {type string; when 1;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("List's key must not have any \"when\" statement.", "/bb:l/x");
+ CHECK_LOG_CTX("List's key must not have any \"when\" statement.", "Path \"/bb:l/x\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module cc {yang-version 1.1;namespace urn:cc;prefix cc;feature f;"
"list l {key x; leaf x {type string; if-feature f;}}}", LYS_IN_YANG, NULL));
@@ -424,43 +417,43 @@ test_node_list(void **state)
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module dd {namespace urn:dd;prefix dd;"
"list l {key x; leaf x {type string; config false;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Key of a configuration list must not be a state leaf.", "/dd:l/x");
+ CHECK_LOG_CTX("Key of a configuration list must not be a state leaf.", "Path \"/dd:l/x\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ee {namespace urn:ee;prefix ee;"
"list l {config false;key x; leaf x {type string; config true;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Configuration node cannot be child of any state data node.", "/ee:l/x");
+ CHECK_LOG_CTX("Configuration node cannot be child of any state data node.", "Path \"/ee:l/x\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ff {namespace urn:ff;prefix ff;"
"list l {key x; leaf-list x {type string;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("The list's key \"x\" not found.", "/ff:l");
+ CHECK_LOG_CTX("The list's key \"x\" not found.", "Path \"/ff:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module gg {namespace urn:gg;prefix gg;"
"list l {key x; unique y;leaf x {type string;} leaf-list y {type string;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Unique's descendant-schema-nodeid \"y\" refers to leaf-list node instead of a leaf.", "/gg:l");
+ CHECK_LOG_CTX("Unique's descendant-schema-nodeid \"y\" refers to leaf-list node instead of a leaf.", "Path \"/gg:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module hh {namespace urn:hh;prefix hh;"
"list l {key x; unique \"x y\";leaf x {type string;} leaf y {config false; type string;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Unique statement \"x y\" refers to leaves with different config type.", "/hh:l");
+ CHECK_LOG_CTX("Unique statement \"x y\" refers to leaves with different config type.", "Path \"/hh:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ii {namespace urn:ii;prefix ii;"
"list l {key x; unique a:x;leaf x {type string;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid descendant-schema-nodeid value \"a:x\" - prefix \"a\" not defined in module \"ii\".", "/ii:l");
+ CHECK_LOG_CTX("Invalid descendant-schema-nodeid value \"a:x\" - prefix \"a\" not defined in module \"ii\".", "Path \"/ii:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module jj {namespace urn:jj;prefix jj;"
"list l {key x; unique c/x;leaf x {type string;}container c {leaf y {type string;}}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid descendant-schema-nodeid value \"c/x\" - target node not found.", "/jj:l");
+ CHECK_LOG_CTX("Invalid descendant-schema-nodeid value \"c/x\" - target node not found.", "Path \"/jj:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module kk {namespace urn:kk;prefix kk;"
"list l {key x; unique c^y;leaf x {type string;}container c {leaf y {type string;}}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid descendant-schema-nodeid value \"c^\" - missing \"/\" as node-identifier separator.", "/kk:l");
+ CHECK_LOG_CTX("Invalid descendant-schema-nodeid value \"c^\" - missing \"/\" as node-identifier separator.", "Path \"/kk:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ll {namespace urn:ll;prefix ll;"
"list l {key \"x y x\";leaf x {type string;}leaf y {type string;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicated key identifier \"x\".", "/ll:l");
+ CHECK_LOG_CTX("Duplicated key identifier \"x\".", "Path \"/ll:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module mm {namespace urn:mm;prefix mm;"
"list l {key x;leaf x {type empty;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("List's key cannot be of \"empty\" type until it is in YANG 1.1 module.", "/mm:l/x");
+ CHECK_LOG_CTX("List key of the \"empty\" type is allowed only in YANG 1.1 modules.", "Path \"/mm:l/x\".");
}
static void
@@ -499,26 +492,26 @@ test_node_choice(void **state)
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa;"
"choice ch {case a {leaf x {type string;}}leaf x {type string;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"x\" of data definition/RPC/action/notification statement.", "/aa:ch/x/x");
+ CHECK_LOG_CTX("Duplicate identifier \"x\" of data definition/RPC/action/notification statement.", "Path \"/aa:ch/x/x\".");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module aa2 {namespace urn:aa2;prefix aa;"
"choice ch {case a {leaf y {type string;}}case b {leaf y {type string;}}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"y\" of data definition/RPC/action/notification statement.", "/aa2:ch/b/y");
+ CHECK_LOG_CTX("Duplicate identifier \"y\" of data definition/RPC/action/notification statement.", "Path \"/aa2:ch/b/y\".");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module bb {namespace urn:bb;prefix bb;"
"choice ch {case a {leaf x {type string;}}leaf a {type string;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"a\" of case statement.", "/bb:ch/a");
+ CHECK_LOG_CTX("Duplicate identifier \"a\" of case statement.", "Path \"/bb:ch/a\".");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module bb2 {namespace urn:bb2;prefix bb;"
"choice ch {case b {leaf x {type string;}}case b {leaf y {type string;}}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"b\" of case statement.", "/bb2:ch/b");
+ CHECK_LOG_CTX("Duplicate identifier \"b\" of case statement.", "Path \"/bb2:ch/b\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ca {namespace urn:ca;prefix ca;"
"choice ch {default c;case a {leaf x {type string;}}case b {leaf y {type string;}}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Default case \"c\" not found.", "/ca:ch");
+ CHECK_LOG_CTX("Default case \"c\" not found.", "Path \"/ca:ch\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module cb {namespace urn:cb;prefix cb; import a {prefix a;}"
"choice ch {default a:a;case a {leaf x {type string;}}case b {leaf y {type string;}}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Default case \"a:a\" not found.", "/cb:ch");
+ CHECK_LOG_CTX("Default case \"a:a\" not found.", "Path \"/cb:ch\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module cc {namespace urn:cc;prefix cc;"
"choice ch {default a;case a {leaf x {mandatory true;type string;}}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Mandatory node \"x\" under the default case \"a\".", "/cc:ch");
+ CHECK_LOG_CTX("Mandatory node \"x\" under the default case \"a\".", "Path \"/cc:ch\".");
/* TODO check with mandatory nodes from augment placed into the case */
}
@@ -544,8 +537,9 @@ test_node_anydata(void **state)
/* invalid */
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa;anydata any;}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL,
- "Invalid keyword \"anydata\" as a child of \"module\" - the statement is allowed only in YANG 1.1 modules.", "Line number 1.");
+ CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid keyword \"anydata\" as a child of \"module\" - the statement is allowed only in YANG 1.1 modules.",
+ "Line number 1.");
}
static void
@@ -579,31 +573,32 @@ test_action(void **state)
/* invalid */
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa;container top {action x;}}",
LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL,
- "Invalid keyword \"action\" as a child of \"container\" - the statement is allowed only in YANG 1.1 modules.", "Line number 1.");
+ CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid keyword \"action\" as a child of \"container\" - the statement is allowed only in YANG 1.1 modules.",
+ "Line number 1.");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module bb {namespace urn:bb;prefix bb;leaf x{type string;} rpc x;}",
LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"x\" of data definition/RPC/action/notification statement.", "/bb:x");
+ CHECK_LOG_CTX("Duplicate identifier \"x\" of data definition/RPC/action/notification statement.", "Path \"/bb:x\".");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module cc {yang-version 1.1; namespace urn:cc;prefix cc;container c {leaf y {type string;} action y;}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"y\" of data definition/RPC/action/notification statement.", "/cc:c/y");
+ CHECK_LOG_CTX("Duplicate identifier \"y\" of data definition/RPC/action/notification statement.", "Path \"/cc:c/y\".");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module dd {yang-version 1.1; namespace urn:dd;prefix dd;container c {action z; action z;}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"z\" of data definition/RPC/action/notification statement.", "/dd:c/z");
+ CHECK_LOG_CTX("Duplicate identifier \"z\" of data definition/RPC/action/notification statement.", "Path \"/dd:c/z\".");
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule eesub {belongs-to ee {prefix ee;} notification w;}");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module ee {yang-version 1.1; namespace urn:ee;prefix ee;include eesub; rpc w;}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"w\" of data definition/RPC/action/notification statement.", "/ee:w");
+ CHECK_LOG_CTX("Duplicate identifier \"w\" of data definition/RPC/action/notification statement.", "Path \"/ee:w\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ff {yang-version 1.1; namespace urn:ff;prefix ff; rpc test {input {container a {leaf b {type string;}}}}"
"augment /test/input/a {action invalid {input {leaf x {type string;}}}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Action \"invalid\" is placed inside another RPC/action.", "/ff:{augment='/test/input/a'}/invalid");
+ CHECK_LOG_CTX("Action \"invalid\" is placed inside another RPC/action.", "Path \"/ff:{augment='/test/input/a'}/invalid\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module gg {yang-version 1.1; namespace urn:gg;prefix gg; notification test {container a {leaf b {type string;}}}"
"augment /test/a {action invalid {input {leaf x {type string;}}}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Action \"invalid\" is placed inside notification.", "/gg:{augment='/test/a'}/invalid");
+ CHECK_LOG_CTX("Action \"invalid\" is placed inside notification.", "Path \"/gg:{augment='/test/a'}/invalid\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module hh {yang-version 1.1; namespace urn:hh;prefix hh; notification test {container a {uses grp;}}"
"grouping grp {action invalid {input {leaf x {type string;}}}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Action \"invalid\" is placed inside notification.", "/hh:test/a/{uses='grp'}/invalid");
+ CHECK_LOG_CTX("Action \"invalid\" is placed inside notification.", "Path \"/hh:test/a/{uses='grp'}/invalid\".");
}
static void
@@ -650,30 +645,31 @@ test_notification(void **state)
/* invalid */
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa;container top {notification x;}}",
LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL,
- "Invalid keyword \"notification\" as a child of \"container\" - the statement is allowed only in YANG 1.1 modules.", "Line number 1.");
+ CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid keyword \"notification\" as a child of \"container\" - the statement is allowed only in YANG 1.1 modules.",
+ "Line number 1.");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module bb {namespace urn:bb;prefix bb;leaf x{type string;} notification x;}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"x\" of data definition/RPC/action/notification statement.", "/bb:x");
+ CHECK_LOG_CTX("Duplicate identifier \"x\" of data definition/RPC/action/notification statement.", "Path \"/bb:x\".");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module cc {yang-version 1.1; namespace urn:cc;prefix cc;container c {leaf y {type string;} notification y;}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"y\" of data definition/RPC/action/notification statement.", "/cc:c/y");
+ CHECK_LOG_CTX("Duplicate identifier \"y\" of data definition/RPC/action/notification statement.", "Path \"/cc:c/y\".");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module dd {yang-version 1.1; namespace urn:dd;prefix dd;container c {notification z; notification z;}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"z\" of data definition/RPC/action/notification statement.", "/dd:c/z");
+ CHECK_LOG_CTX("Duplicate identifier \"z\" of data definition/RPC/action/notification statement.", "Path \"/dd:c/z\".");
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule eesub {belongs-to ee {prefix ee;} rpc w;}");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module ee {yang-version 1.1; namespace urn:ee;prefix ee;include eesub; notification w;}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Duplicate identifier \"w\" of data definition/RPC/action/notification statement.", "/ee:w");
+ CHECK_LOG_CTX("Duplicate identifier \"w\" of data definition/RPC/action/notification statement.", "Path \"/ee:w\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ff {yang-version 1.1; namespace urn:ff;prefix ff; rpc test {input {container a {leaf b {type string;}}}}"
"augment /test/input/a {notification invalid {leaf x {type string;}}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Notification \"invalid\" is placed inside RPC/action.", "/ff:{augment='/test/input/a'}/invalid");
+ CHECK_LOG_CTX("Notification \"invalid\" is placed inside RPC/action.", "Path \"/ff:{augment='/test/input/a'}/invalid\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module gg {yang-version 1.1; namespace urn:gg;prefix gg; notification test {container a {leaf b {type string;}}}"
"augment /test/a {notification invalid {leaf x {type string;}}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Notification \"invalid\" is placed inside another notification.", "/gg:{augment='/test/a'}/invalid");
+ CHECK_LOG_CTX("Notification \"invalid\" is placed inside another notification.", "Path \"/gg:{augment='/test/a'}/invalid\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module hh {yang-version 1.1; namespace urn:hh;prefix hh; rpc test {input {container a {uses grp;}}}"
"grouping grp {notification invalid {leaf x {type string;}}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Notification \"invalid\" is placed inside RPC/action.", "/hh:test/input/a/{uses='grp'}/invalid");
+ CHECK_LOG_CTX("Notification \"invalid\" is placed inside RPC/action.", "Path \"/hh:test/input/a/{uses='grp'}/invalid\".");
}
/**
@@ -686,21 +682,6 @@ test_type_range(void **state)
struct lys_module *mod;
struct lysc_type *type;
-#if 0
- /*test about int8 should be in tests/utests/types/int8.c*/
- assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module a {namespace urn:a;prefix a;leaf l {type int8 {range min..10|max;}}}", LYS_IN_YANG, &mod));
- type = ((struct lysc_node_leaf *)mod->compiled->data)->type;
- assert_non_null(type);
- assert_int_equal(LY_TYPE_INT8, type->basetype);
- assert_non_null(((struct lysc_type_num *)type)->range);
- assert_non_null(((struct lysc_type_num *)type)->range->parts);
- assert_int_equal(2, LY_ARRAY_COUNT(((struct lysc_type_num *)type)->range->parts));
- assert_int_equal(-128, ((struct lysc_type_num *)type)->range->parts[0].min_64);
- assert_int_equal(10, ((struct lysc_type_num *)type)->range->parts[0].max_64);
- assert_int_equal(127, ((struct lysc_type_num *)type)->range->parts[1].min_64);
- assert_int_equal(127, ((struct lysc_type_num *)type)->range->parts[1].max_64);
-#endif
-
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module b {namespace urn:b;prefix b;leaf l {type int16 {range min..10|max;}}}", LYS_IN_YANG, &mod));
type = ((struct lysc_node_leaf *)mod->compiled->data)->type;
assert_non_null(type);
@@ -937,83 +918,56 @@ test_type_length(void **state)
assert_int_equal(10, ((struct lysc_type_bin *)type)->length->parts[0].min_u64);
assert_int_equal(100, ((struct lysc_type_bin *)type)->length->parts[0].max_u64);
- /* new string is tested in file ./tests/utests/types/string.c */
-#if 0
- assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module l {namespace urn:l;prefix l;typedef mytype {type string {length 10..100;}}"
- "typedef mytype2 {type mytype {pattern '[0-9]*';}} leaf l {type mytype2 {pattern '[0-4]*';}}}", LYS_IN_YANG, &mod));
- type = ((struct lysc_node_leaf *)mod->compiled->data)->type;
- assert_non_null(type);
- assert_int_equal(LY_TYPE_STRING, type->basetype);
- assert_int_equal(1, type->refcount);
- assert_non_null(((struct lysc_type_str *)type)->length);
- assert_non_null(((struct lysc_type_str *)type)->length->parts);
- assert_int_equal(1, LY_ARRAY_COUNT(((struct lysc_type_str *)type)->length->parts));
- assert_int_equal(10, ((struct lysc_type_str *)type)->length->parts[0].min_u64);
- assert_int_equal(100, ((struct lysc_type_str *)type)->length->parts[0].max_u64);
-
- assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module m {namespace urn:m;prefix m;typedef mytype {type string {length 10;}}"
- "leaf l {type mytype {length min..max;}}}", LYS_IN_YANG, &mod));
- type = ((struct lysc_node_leaf *)mod->compiled->data)->type;
- assert_non_null(type);
- assert_int_equal(LY_TYPE_STRING, type->basetype);
- assert_int_equal(1, type->refcount);
- assert_non_null(((struct lysc_type_str *)type)->length);
- assert_non_null(((struct lysc_type_str *)type)->length->parts);
- assert_int_equal(1, LY_ARRAY_COUNT(((struct lysc_type_str *)type)->length->parts));
- assert_int_equal(10, ((struct lysc_type_str *)type)->length->parts[0].min_u64);
- assert_int_equal(10, ((struct lysc_type_str *)type)->length->parts[0].max_u64);
-#endif
-
/* invalid values */
assert_int_equal(LY_EDENIED, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa;leaf l {type binary {length -10;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - value \"-10\" does not fit the type limitations.", "/aa:l");
+ CHECK_LOG_CTX("Invalid length restriction - value \"-10\" does not fit the type limitations.", "Path \"/aa:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module bb {namespace urn:bb;prefix bb;leaf l {type binary {length 18446744073709551616;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - invalid value \"18446744073709551616\".", "/bb:l");
+ CHECK_LOG_CTX("Invalid length restriction - invalid value \"18446744073709551616\".", "Path \"/bb:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module cc {namespace urn:cc;prefix cc;leaf l {type binary {length \"max .. 10\";}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - unexpected data after max keyword (.. 10).", "/cc:l");
+ CHECK_LOG_CTX("Invalid length restriction - unexpected data after max keyword (.. 10).", "Path \"/cc:l\".");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module dd {namespace urn:dd;prefix dd;leaf l {type binary {length 50..10;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - values are not in ascending order (10).", "/dd:l");
+ CHECK_LOG_CTX("Invalid length restriction - values are not in ascending order (10).", "Path \"/dd:l\".");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module ee {namespace urn:ee;prefix ee;leaf l {type binary {length \"50 | 10\";}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - values are not in ascending order (10).", "/ee:l");
+ CHECK_LOG_CTX("Invalid length restriction - values are not in ascending order (10).", "Path \"/ee:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ff {namespace urn:ff;prefix ff;leaf l {type binary {length \"x\";}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - unexpected data (x).", "/ff:l");
+ CHECK_LOG_CTX("Invalid length restriction - unexpected data (x).", "Path \"/ff:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module gg {namespace urn:gg;prefix gg;leaf l {type binary {length \"50 | min\";}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - unexpected data before min keyword (50 | ).", "/gg:l");
+ CHECK_LOG_CTX("Invalid length restriction - unexpected data before min keyword (50 | ).", "Path \"/gg:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module hh {namespace urn:hh;prefix hh;leaf l {type binary {length \"| 50\";}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - unexpected beginning of the expression (| 50).", "/hh:l");
+ CHECK_LOG_CTX("Invalid length restriction - unexpected beginning of the expression (| 50).", "Path \"/hh:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ii {namespace urn:ii;prefix ii;leaf l {type binary {length \"10 ..\";}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - unexpected end of the expression after \"..\" (10 ..).", "/ii:l");
+ CHECK_LOG_CTX("Invalid length restriction - unexpected end of the expression after \"..\" (10 ..).", "Path \"/ii:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module jj {namespace urn:jj;prefix jj;leaf l {type binary {length \".. 10\";}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - unexpected \"..\" without a lower bound.", "/jj:l");
+ CHECK_LOG_CTX("Invalid length restriction - unexpected \"..\" without a lower bound.", "Path \"/jj:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module kk {namespace urn:kk;prefix kk;leaf l {type binary {length \"10 |\";}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - unexpected end of the expression (10 |).", "/kk:l");
+ CHECK_LOG_CTX("Invalid length restriction - unexpected end of the expression (10 |).", "Path \"/kk:l\".");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module kl {namespace urn:kl;prefix kl;leaf l {type binary {length \"10..20 | 15..30\";}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - values are not in ascending order (15).", "/kl:l");
+ CHECK_LOG_CTX("Invalid length restriction - values are not in ascending order (15).", "Path \"/kl:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ll {namespace urn:ll;prefix ll;typedef mytype {type binary {length 10;}}"
"leaf l {type mytype {length 11;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - the derived restriction (11) is not equally or more limiting.", "/ll:l");
+ CHECK_LOG_CTX("Invalid length restriction - the derived restriction (11) is not equally or more limiting.", "Path \"/ll:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module mm {namespace urn:mm;prefix mm;typedef mytype {type binary {length 10..100;}}"
"leaf l {type mytype {length 1..11;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - the derived restriction (1..11) is not equally or more limiting.", "/mm:l");
+ CHECK_LOG_CTX("Invalid length restriction - the derived restriction (1..11) is not equally or more limiting.", "Path \"/mm:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module nn {namespace urn:nn;prefix nn;typedef mytype {type binary {length 10..100;}}"
"leaf l {type mytype {length 20..110;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - the derived restriction (20..110) is not equally or more limiting.", "/nn:l");
+ CHECK_LOG_CTX("Invalid length restriction - the derived restriction (20..110) is not equally or more limiting.", "Path \"/nn:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module oo {namespace urn:oo;prefix oo;typedef mytype {type binary {length 10..100;}}"
"leaf l {type mytype {length 20..30|110..120;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - the derived restriction (20..30|110..120) is not equally or more limiting.", "/oo:l");
+ CHECK_LOG_CTX("Invalid length restriction - the derived restriction (20..30|110..120) is not equally or more limiting.", "Path \"/oo:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module pp {namespace urn:pp;prefix pp;typedef mytype {type binary {length 10..11;}}"
"leaf l {type mytype {length 15;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - the derived restriction (15) is not equally or more limiting.", "/pp:l");
+ CHECK_LOG_CTX("Invalid length restriction - the derived restriction (15) is not equally or more limiting.", "Path \"/pp:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module qq {namespace urn:qq;prefix qq;typedef mytype {type binary {length 10..20|30..40;}}"
"leaf l {type mytype {length 15..35;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - the derived restriction (15..35) is not equally or more limiting.", "/qq:l");
+ CHECK_LOG_CTX("Invalid length restriction - the derived restriction (15..35) is not equally or more limiting.", "Path \"/qq:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module rr {namespace urn:rr;prefix rr;typedef mytype {type binary {length 10;}}"
"leaf l {type mytype {length 10..35;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid length restriction - the derived restriction (10..35) is not equally or more limiting.", "/rr:l");
+ CHECK_LOG_CTX("Invalid length restriction - the derived restriction (10..35) is not equally or more limiting.", "Path \"/rr:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ss {namespace urn:ss;prefix ss;leaf l {type binary {pattern '[0-9]*';}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid type restrictions for binary type.", "/ss:l");
+ CHECK_LOG_CTX("Invalid type restrictions for binary type.", "Path \"/ss:l\".");
}
static void
@@ -1152,61 +1106,63 @@ test_type_enum(void **state)
/* invalid cases */
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; feature f; leaf l {type enumeration {"
"enum one {if-feature f;}}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL,
- "Invalid keyword \"if-feature\" as a child of \"enum\" - the statement is allowed only in YANG 1.1 modules.", "Line number 1.");
+ CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid keyword \"if-feature\" as a child of \"enum\" - the statement is allowed only in YANG 1.1 modules.",
+ "Line number 1.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
"enum one {value -2147483649;}}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL,
- "Invalid value \"-2147483649\" of \"value\".", "Line number 1.");
+ CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid value \"-2147483649\" of \"value\".", "Line number 1.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
"enum one {value 2147483648;}}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL,
- "Invalid value \"2147483648\" of \"value\".", "Line number 1.");
+ CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid value \"2147483648\" of \"value\".", "Line number 1.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
"enum one; enum one;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL,
- "Duplicate identifier \"one\" of enum statement.", "Line number 1.");
+ CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"one\" of enum statement.", "Line number 1.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
"enum '';}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL,
- "Enum name must not be zero-length.", "Line number 1.");
+ CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL);
+ CHECK_LOG_CTX("Enum name must not be zero-length.", "Line number 1.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
"enum ' x';}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL,
- "Enum name must not have any leading or trailing whitespaces (\" x\").", "Line number 1.");
+ CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL);
+ CHECK_LOG_CTX("Enum name must not have any leading or trailing whitespaces (\" x\").", "Line number 1.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
"enum 'x ';}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL,
- "Enum name must not have any leading or trailing whitespaces (\"x \").", "Line number 1.");
+ CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL);
+ CHECK_LOG_CTX("Enum name must not have any leading or trailing whitespaces (\"x \").", "Line number 1.");
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
"enum 'inva\nlid';}}}", LYS_IN_YANG, &mod));
CHECK_LOG_CTX("Control characters in enum name should be avoided (\"inva\nlid\", character number 5).", NULL);
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module bb {namespace urn:bb;prefix bb; leaf l {type enumeration;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Missing enum substatement for enumeration type.", "/bb:l");
+ CHECK_LOG_CTX("Missing enum substatement for enumeration type.", "Path \"/bb:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module cc {yang-version 1.1;namespace urn:cc;prefix cc;typedef mytype {type enumeration {enum one;}}"
"leaf l {type mytype {enum two;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid enumeration - derived type adds new item \"two\".", "/cc:l");
+ CHECK_LOG_CTX("Invalid enumeration - derived type adds new item \"two\".", "Path \"/cc:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module dd {yang-version 1.1;namespace urn:dd;prefix dd;typedef mytype {type enumeration {enum one;}}"
"leaf l {type mytype {enum one {value 1;}}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid enumeration - value of the item \"one\" has changed from 0 to 1 in the derived type.", "/dd:l");
+ CHECK_LOG_CTX("Invalid enumeration - value of the item \"one\" has changed from 0 to 1 in the derived type.", "Path \"/dd:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ee {namespace urn:ee;prefix ee;leaf l {type enumeration {enum x {value 2147483647;}enum y;}}}",
LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid enumeration - it is not possible to auto-assign enum value for \"y\" since the highest value is already 2147483647.", "/ee:l");
+ CHECK_LOG_CTX("Invalid enumeration - it is not possible to auto-assign enum value for \"y\" since the highest value is already 2147483647.",
+ "Path \"/ee:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ff {namespace urn:ff;prefix ff;leaf l {type enumeration {enum x {value 1;}enum y {value 1;}}}}",
LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid enumeration - value 1 collide in items \"y\" and \"x\".", "/ff:l");
+ CHECK_LOG_CTX("Invalid enumeration - value 1 collide in items \"y\" and \"x\".", "Path \"/ff:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module gg {namespace urn:gg;prefix gg;typedef mytype {type enumeration;}"
"leaf l {type mytype {enum one;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Missing enum substatement for enumeration type mytype.", "/gg:l");
+ CHECK_LOG_CTX("Missing enum substatement for enumeration type mytype.", "Path \"/gg:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module hh {namespace urn:hh;prefix hh; typedef mytype {type enumeration {enum one;}}"
"leaf l {type mytype {enum one;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Enumeration type can be subtyped only in YANG 1.1 modules.", "/hh:l");
+ CHECK_LOG_CTX("Enumeration type can be subtyped only in YANG 1.1 modules.", "Path \"/hh:l\".");
}
static void
@@ -1256,43 +1212,43 @@ test_type_dec64(void **state)
/* invalid cases */
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type decimal64 {fraction-digits 0;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL,
- "Invalid value \"0\" of \"fraction-digits\".", "Line number 1.");
+ CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid value \"0\" of \"fraction-digits\".", "Line number 1.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type decimal64 {fraction-digits -1;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL,
- "Invalid value \"-1\" of \"fraction-digits\".", "Line number 1.");
+ CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid value \"-1\" of \"fraction-digits\".", "Line number 1.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type decimal64 {fraction-digits 19;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL,
- "Value \"19\" is out of \"fraction-digits\" bounds.", "Line number 1.");
+ CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL);
+ CHECK_LOG_CTX("Value \"19\" is out of \"fraction-digits\" bounds.", "Line number 1.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type decimal64;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Missing fraction-digits substatement for decimal64 type.", "/aa:l");
+ CHECK_LOG_CTX("Missing fraction-digits substatement for decimal64 type.", "Path \"/aa:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ab {namespace urn:ab;prefix ab; typedef mytype {type decimal64;}leaf l {type mytype;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Missing fraction-digits substatement for decimal64 type mytype.", "/ab:l");
+ CHECK_LOG_CTX("Missing fraction-digits substatement for decimal64 type mytype.", "Path \"/ab:l\".");
assert_int_equal(LY_EINVAL, lys_parse_mem(UTEST_LYCTX, "module bb {namespace urn:bb;prefix bb; leaf l {type decimal64 {fraction-digits 2;"
"range '3.142';}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Range boundary \"3.142\" of decimal64 type exceeds defined number (2) of fraction digits.", "/bb:l");
+ CHECK_LOG_CTX("Range boundary \"3.142\" of decimal64 type exceeds defined number (2) of fraction digits.", "Path \"/bb:l\".");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module cc {namespace urn:cc;prefix cc; leaf l {type decimal64 {fraction-digits 2;"
"range '4 | 3.14';}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid range restriction - values are not in ascending order (3.14).", "/cc:l");
+ CHECK_LOG_CTX("Invalid range restriction - values are not in ascending order (3.14).", "Path \"/cc:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module dd {namespace urn:dd;prefix dd; typedef mytype {type decimal64 {fraction-digits 2;}}"
"leaf l {type mytype {fraction-digits 3;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid fraction-digits substatement for type not directly derived from decimal64 built-in type.", "/dd:l");
+ CHECK_LOG_CTX("Invalid fraction-digits substatement for type not directly derived from decimal64 built-in type.", "Path \"/dd:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module de {namespace urn:de;prefix de; typedef mytype {type decimal64 {fraction-digits 2;}}"
"typedef mytype2 {type mytype {fraction-digits 3;}}leaf l {type mytype2;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid fraction-digits substatement for type \"mytype2\" not directly derived from decimal64 built-in type.", "/de:l");
+ CHECK_LOG_CTX("Invalid fraction-digits substatement for type \"mytype2\" not directly derived from decimal64 built-in type.", "Path \"/de:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ee {namespace urn:ee;prefix ee;typedef mytype {type decimal64 {"
"fraction-digits 18;range '-10 .. 0';}}leaf l {type mytype;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid range restriction - invalid value \"-10000000000000000000\".", "/ee:l");
+ CHECK_LOG_CTX("Invalid range restriction - invalid value \"-10000000000000000000\".", "Path \"/ee:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ee {namespace urn:ee;prefix ee;typedef mytype {type decimal64 {"
"fraction-digits 18;range '0 .. 10';}}leaf l {type mytype;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid range restriction - invalid value \"10000000000000000000\".", "/ee:l");
+ CHECK_LOG_CTX("Invalid range restriction - invalid value \"10000000000000000000\".", "Path \"/ee:l\".");
}
static void
@@ -1321,11 +1277,11 @@ test_type_instanceid(void **state)
/* invalid cases */
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {require-instance yes;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL,
- "Invalid value \"yes\" of \"require-instance\".", "Line number 1.");
+ CHECK_LOG_CTX("Parsing module \"aa\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid value \"yes\" of \"require-instance\".", "Line number 1.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {fraction-digits 1;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid type restrictions for instance-identifier type.", "/aa:l");
+ CHECK_LOG_CTX("Invalid type restrictions for instance-identifier type.", "Path \"/aa:l\".");
}
static ly_bool
@@ -1721,29 +1677,29 @@ test_type_identityref(void **state)
/* invalid cases */
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; leaf l {type identityref;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Missing base substatement for identityref type.", "/aa:l");
+ CHECK_LOG_CTX("Missing base substatement for identityref type.", "Path \"/aa:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module bb {namespace urn:bb;prefix bb; typedef mytype {type identityref;}"
"leaf l {type mytype;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Missing base substatement for identityref type mytype.", "/bb:l");
+ CHECK_LOG_CTX("Missing base substatement for identityref type mytype.", "Path \"/bb:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module cc {namespace urn:cc;prefix cc; identity i; typedef mytype {type identityref {base i;}}"
"leaf l {type mytype {base i;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid base substatement for the type not directly derived from identityref built-in type.", "/cc:l");
+ CHECK_LOG_CTX("Invalid base substatement for the type not directly derived from identityref built-in type.", "Path \"/cc:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module dd {namespace urn:dd;prefix dd; identity i; typedef mytype {type identityref {base i;}}"
"typedef mytype2 {type mytype {base i;}}leaf l {type mytype2;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid base substatement for the type \"mytype2\" not directly derived from identityref built-in type.", "/dd:l");
+ CHECK_LOG_CTX("Invalid base substatement for the type \"mytype2\" not directly derived from identityref built-in type.", "Path \"/dd:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ee {namespace urn:ee;prefix ee; identity i; identity j;"
"leaf l {type identityref {base i;base j;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Multiple bases in identityref type are allowed only in YANG 1.1 modules.", "/ee:l");
+ CHECK_LOG_CTX("Multiple bases in identityref type are allowed only in YANG 1.1 modules.", "Path \"/ee:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ff {namespace urn:ff;prefix ff; identity i;leaf l {type identityref {base j;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Unable to find base (j) of identityref.", "/ff:l");
+ CHECK_LOG_CTX("Unable to find base (j) of identityref.", "Path \"/ff:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module gg {namespace urn:gg;prefix gg;leaf l {type identityref {base x:j;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid prefix used for base (x:j) of identityref.", "/gg:l");
+ CHECK_LOG_CTX("Invalid prefix used for base (x:j) of identityref.", "Path \"/gg:l\".");
}
static void
@@ -1759,18 +1715,27 @@ test_type_leafref(void **state)
path = "invalid_path";
assert_int_equal(LY_EVALID, ly_path_parse(UTEST_LYCTX, NULL, path, strlen(path), 1, LY_PATH_BEGIN_EITHER,
LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &expr));
+ CHECK_LOG_CTX("Unexpected XPath token \"NameTest\" (\"invalid_path\"), expected \"..\".", NULL);
+
path = "..";
assert_int_equal(LY_EVALID, ly_path_parse(UTEST_LYCTX, NULL, path, strlen(path), 1, LY_PATH_BEGIN_EITHER,
LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &expr));
+ CHECK_LOG_CTX("Unexpected XPath expression end.", NULL);
+
path = "..[";
assert_int_equal(LY_EVALID, ly_path_parse(UTEST_LYCTX, NULL, path, strlen(path), 1, LY_PATH_BEGIN_EITHER,
LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &expr));
+ CHECK_LOG_CTX("Unexpected XPath token \"[\" (\"[\"), expected \"Operator(Path)\".", NULL);
+
path = "../";
assert_int_equal(LY_EVALID, ly_path_parse(UTEST_LYCTX, NULL, path, strlen(path), 1, LY_PATH_BEGIN_EITHER,
LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &expr));
+ CHECK_LOG_CTX("Unexpected XPath expression end.", NULL);
+
path = "/";
assert_int_equal(LY_EVALID, ly_path_parse(UTEST_LYCTX, NULL, path, strlen(path), 1, LY_PATH_BEGIN_EITHER,
LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &expr));
+ CHECK_LOG_CTX("Unexpected XPath expression end.", NULL);
path = "../../pref:id/xxx[predicate]/invalid!!!";
assert_int_equal(LY_EVALID, ly_path_parse(UTEST_LYCTX, NULL, path, strlen(path), 1, LY_PATH_BEGIN_EITHER,
@@ -1861,6 +1826,7 @@ test_type_leafref(void **state)
"leaf target {if-feature 'f1'; type boolean;}}";
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, &mod));
CHECK_LOG_CTX("Target of leafref \"ref1\" cannot be referenced because it is disabled.", "Schema location \"/e:ref1\".");
+ CHECK_LOG_CTX("Not found node \"target\" in path.", "Schema location \"/e:ref1\".");
str = "module en {yang-version 1.1;namespace urn:en;prefix en;feature f1;"
"leaf ref1 {if-feature 'f1'; type leafref {path /target;}}"
@@ -1881,6 +1847,7 @@ test_type_leafref(void **state)
"leaf ref {must \"/cl:h > 0\"; type uint16;}}", LYS_IN_YANG, &mod));
ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_REF_IMPLEMENTED);
CHECK_LOG_CTX("Target of leafref \"g\" cannot be referenced because it is disabled.", "Schema location \"/cl:g\".");
+ CHECK_LOG_CTX("Not found node \"f\" in path.", "Schema location \"/cl:g\".");
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module f {namespace urn:f;prefix f;"
"list interface{key name;leaf name{type string;}list address {key ip;leaf ip {type string;}}}"
@@ -1956,6 +1923,13 @@ test_type_leafref(void **state)
assert_int_equal(LY_TYPE_BOOL, ((struct lysc_node_leaf *)mod->compiled->data)->dflt->realtype->basetype);
assert_int_equal(1, ((struct lysc_node_leaf *)mod->compiled->data)->dflt->boolean);
+ /* union reference */
+ assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module m {namespace urn:m;prefix m;"
+ "typedef s-ref {type union {type leafref {path '/str';}}}"
+ "leaf str {type string {length \"1..16\" {error-message \"Custom message\";}}}"
+ "leaf ref1 {type s-ref;}"
+ "leaf ref2 {type s-ref;}}", LYS_IN_YANG, NULL));
+
/* invalid paths */
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa;container a {leaf target2 {type uint8;}}"
"leaf ref1 {type leafref {path ../a/invalid;}}}", LYS_IN_YANG, &mod));
@@ -1972,8 +1946,8 @@ test_type_leafref(void **state)
CHECK_LOG_CTX("List predicate defined for container \"a\" in path.", "Schema location \"/dd:ref1\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ee {namespace urn:ee;prefix ee;\n container a {leaf target2 {type uint8;}}\n"
"leaf ref1 {type leafref {path /a!invalid;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"ee\" failed.", NULL,
- "Invalid character 0x21 ('!'), perhaps \"a\" is supposed to be a function call.", "Line number 3.");
+ CHECK_LOG_CTX("Parsing module \"ee\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid character 0x21 ('!'), perhaps \"a\" is supposed to be a function call.", "Line number 3.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ff {namespace urn:ff;prefix ff;container a {leaf target2 {type uint8;}}"
"leaf ref1 {type leafref {path /a;}}}", LYS_IN_YANG, &mod));
CHECK_LOG_CTX("Invalid leafref path \"/a\" - target node is container instead of leaf or leaf-list.", "Schema location \"/ff:ref1\".");
@@ -1983,36 +1957,36 @@ test_type_leafref(void **state)
"Schema location \"/gg:ref1\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module hh {namespace urn:hh;prefix hh;"
"leaf ref1 {type leafref;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Missing path substatement for leafref type.", "/hh:ref1");
+ CHECK_LOG_CTX("Missing path substatement for leafref type.", "Path \"/hh:ref1\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ii {namespace urn:ii;prefix ii;typedef mytype {type leafref;}"
"leaf ref1 {type mytype;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Missing path substatement for leafref type mytype.", "/ii:ref1");
+ CHECK_LOG_CTX("Missing path substatement for leafref type mytype.", "Path \"/ii:ref1\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module kk {namespace urn:kk;prefix kk;"
"leaf ref {type leafref {path /target;}}leaf target {type string;config false;}}", LYS_IN_YANG, &mod));
CHECK_LOG_CTX("Invalid leafref path \"/target\" - target is supposed to represent configuration data (as the leafref does), but it does not.", "Schema location \"/kk:ref\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ll {namespace urn:ll;prefix ll;"
"leaf ref {type leafref {path /target; require-instance true;}}leaf target {type string;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Leafref type can be restricted by require-instance statement only in YANG 1.1 modules.", "/ll:ref");
+ CHECK_LOG_CTX("Leafref type can be restricted by require-instance statement only in YANG 1.1 modules.", "Path \"/ll:ref\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module mm {namespace urn:mm;prefix mm;typedef mytype {type leafref {path /target;require-instance false;}}"
"leaf ref {type mytype;}leaf target {type string;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Leafref type \"mytype\" can be restricted by require-instance statement only in YANG 1.1 modules.", "/mm:ref");
+ CHECK_LOG_CTX("Leafref type \"mytype\" can be restricted by require-instance statement only in YANG 1.1 modules.", "Path \"/mm:ref\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module nn {namespace urn:nn;prefix nn;\n"
"list interface{key name;leaf name{type string;}leaf ip {type string;}}\n"
"leaf ifname{type leafref{ path \"../interface/name\";}}\n"
"leaf address {type leafref{\n path \"/interface[name is current()/../ifname]/ip\";}}}",
LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"nn\" failed.", NULL,
- "Invalid character 0x69 ('i'), perhaps \"name\" is supposed to be a function call.", "Line number 5.");
+ CHECK_LOG_CTX("Parsing module \"nn\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid character 0x69 ('i'), perhaps \"name\" is supposed to be a function call.", "Line number 5.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module oo {namespace urn:oo;prefix oo;\n"
"list interface{key name;leaf name{type string;}leaf ip {type string;}}\n"
"leaf ifname{type leafref{ path \"../interface/name\";}}\n"
"leaf address {type leafref{\n path \"/interface[name=current()/../ifname/ip\";}}}",
LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"oo\" failed.", NULL,
- "Unexpected XPath expression end.", "Line number 5.");
+ CHECK_LOG_CTX("Parsing module \"oo\" failed.", NULL);
+ CHECK_LOG_CTX("Unexpected XPath expression end.", "Line number 5.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module pp {namespace urn:pp;prefix pp;"
"list interface{key name;leaf name{type string;}leaf ip {type string;}}"
@@ -2034,56 +2008,56 @@ test_type_leafref(void **state)
"leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}\n"
"leaf address {type leafref{ path \"/interface[name=current() / .. / ifname][name=current()/../test]/ip\";}}}",
LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"rr\" failed.", NULL,
- "Duplicate predicate key \"name\" in path.", "Line number 4.");
+ CHECK_LOG_CTX("Parsing module \"rr\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate predicate key \"name\" in path.", "Line number 4.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ss {namespace urn:ss;prefix ss;\n"
"list interface{key name;leaf name{type string;}leaf ip {type string;}}\n"
"leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}\n"
"leaf address {type leafref{ path \"/interface[name = ../ifname]/ip\";}}}",
LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"ss\" failed.", NULL,
- "Unexpected XPath token \"..\" (\"../ifname]/ip\"), expected \"FunctionName\".", "Line number 4.");
+ CHECK_LOG_CTX("Parsing module \"ss\" failed.", NULL);
+ CHECK_LOG_CTX("Unexpected XPath token \"..\" (\"../ifname]/ip\"), expected \"FunctionName\".", "Line number 4.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module tt {namespace urn:tt;prefix tt;\n"
"list interface{key name;leaf name{type string;}leaf ip {type string;}}\n"
"leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}\n"
"leaf address {type leafref{ path \"/interface[name = current()../ifname]/ip\";}}}",
LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"tt\" failed.", NULL,
- "Unexpected XPath token \"..\" (\"../ifname]/ip\"), expected \"]\".", "Line number 4.");
+ CHECK_LOG_CTX("Parsing module \"tt\" failed.", NULL);
+ CHECK_LOG_CTX("Unexpected XPath token \"..\" (\"../ifname]/ip\"), expected \"Operator(Path)\".", "Line number 4.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module uu {namespace urn:uu;prefix uu;\n"
"list interface{key name;leaf name{type string;}leaf ip {type string;}}\n"
"leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}\n"
"leaf address {type leafref{ path \"/interface[name = current()/..ifname]/ip\";}}}",
LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"uu\" failed.", NULL,
- "Invalid character 'i'[31] of expression '/interface[name = current()/..ifname]/ip'.", "Line number 4.");
+ CHECK_LOG_CTX("Parsing module \"uu\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid character 'i'[31] of expression '/interface[name = current()/..ifname]/ip'.", "Line number 4.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module vv {namespace urn:vv;prefix vv;\n"
"list interface{key name;leaf name{type string;}leaf ip {type string;}}\n"
"leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}\n"
"leaf address {type leafref{ path \"/interface[name = current()/ifname]/ip\";}}}",
LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"vv\" failed.", NULL,
- "Unexpected XPath token \"NameTest\" (\"ifname]/ip\"), expected \"..\".", "Line number 4.");
+ CHECK_LOG_CTX("Parsing module \"vv\" failed.", NULL);
+ CHECK_LOG_CTX("Unexpected XPath token \"NameTest\" (\"ifname]/ip\"), expected \"..\".", "Line number 4.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ww {namespace urn:ww;prefix ww;\n"
"list interface{key name;leaf name{type string;}leaf ip {type string;}}\n"
"leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}\n"
"leaf address {type leafref{ path \"/interface[name = current()/../]/ip\";}}}",
LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"ww\" failed.", NULL,
- "Unexpected XPath token \"]\" (\"]/ip\").", "Line number 4.");
+ CHECK_LOG_CTX("Parsing module \"ww\" failed.", NULL);
+ CHECK_LOG_CTX("Unexpected XPath token \"]\" (\"]/ip\"), expected \"NameTest\".", "Line number 4.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module xx {namespace urn:xx;prefix xx;\n"
"list interface{key name;leaf name{type string;}leaf ip {type string;}}\n"
"leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}\n"
"leaf address {type leafref{ path \"/interface[name = current()/../#node]/ip\";}}}",
LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Parsing module \"xx\" failed.", NULL,
- "Invalid character '#'[32] of expression '/interface[name = current()/../#node]/ip'.", "Line number 4.");
+ CHECK_LOG_CTX("Parsing module \"xx\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid character '#'[32] of expression '/interface[name = current()/../#node]/ip'.", "Line number 4.");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module yy {namespace urn:yy;prefix yy;\n"
"list interface{key name;leaf name{type string;}leaf ip {type string;}}\n"
@@ -2143,7 +2117,7 @@ test_type_empty(void **state)
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module bb {namespace urn:bb;prefix bb;typedef mytype {type empty; default x;}"
"leaf l {type mytype;}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Invalid type \"mytype\" - \"empty\" type must not have a default value (x).", "/bb:l");
+ CHECK_LOG_CTX("Invalid type \"mytype\" - \"empty\" type must not have a default value (x).", "Path \"/bb:l\".");
}
static void
@@ -2197,25 +2171,25 @@ test_type_union(void **state)
/* invalid unions */
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa;typedef mytype {type union;}"
"leaf l {type mytype;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Missing type substatement for union type mytype.", "/aa:l");
+ CHECK_LOG_CTX("Missing type substatement for union type mytype.", "Path \"/aa:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module bb {namespace urn:bb;prefix bb;leaf l {type union;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Missing type substatement for union type.", "/bb:l");
+ CHECK_LOG_CTX("Missing type substatement for union type.", "Path \"/bb:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module cc {namespace urn:cc;prefix cc;typedef mytype {type union{type int8; type string;}}"
"leaf l {type mytype {type string;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid type substatement for the type not directly derived from union built-in type.", "/cc:l");
+ CHECK_LOG_CTX("Invalid type substatement for the type not directly derived from union built-in type.", "Path \"/cc:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module dd {namespace urn:dd;prefix dd;typedef mytype {type union{type int8; type string;}}"
"typedef mytype2 {type mytype {type string;}}leaf l {type mytype2;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid type substatement for the type \"mytype2\" not directly derived from union built-in type.", "/dd:l");
+ CHECK_LOG_CTX("Invalid type substatement for the type \"mytype2\" not directly derived from union built-in type.", "Path \"/dd:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ee {namespace urn:ee;prefix ee;typedef mytype {type union{type mytype; type string;}}"
"leaf l {type mytype;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid \"mytype\" type reference - circular chain of types detected.", "/ee:l");
+ CHECK_LOG_CTX("Invalid \"mytype\" type reference - circular chain of types detected.", "Path \"/ee:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ef {namespace urn:ef;prefix ef;typedef mytype {type mytype2;}"
"typedef mytype2 {type mytype;} leaf l {type mytype;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid \"mytype\" type reference - circular chain of types detected.", "/ef:l");
+ CHECK_LOG_CTX("Invalid \"mytype\" type reference - circular chain of types detected.", "Path \"/ef:l\".");
}
static void
@@ -2304,20 +2278,173 @@ test_type_dflt(void **state)
}
static void
+test_type_exts(void **state)
+{
+ const char *schema1, *schema2, *schema3, *schema4;
+ struct lys_module *mod;
+ const struct lysc_node *snode;
+ struct lysc_type *type;
+ struct lysc_type_union *type_u;
+
+ schema1 = "module my-extensions {\n"
+ " namespace \"urn:my-extensions\";\n"
+ " prefix my-ext;\n"
+ "\n"
+ " extension shortdesc {\n"
+ " argument shortdsc;\n"
+ " }\n"
+ "}\n";
+ schema2 = "module module-inet {\n"
+ " yang-version 1.1;\n"
+ " namespace \"urn:module-inet\";\n"
+ " prefix mod-inet;\n"
+ "\n"
+ " import ietf-inet-types {\n"
+ " prefix inet;\n"
+ " }\n"
+ "\n"
+ " import my-extensions {\n"
+ " prefix my-ext;\n"
+ " }\n"
+ "\n"
+ " typedef domain-name {\n"
+ " type inet:domain-name {\n"
+ " my-ext:shortdesc \"<host-name>\";\n"
+ " }\n"
+ " }\n"
+ "\n"
+ " typedef ipv4-address {\n"
+ " type inet:ipv4-address-no-zone {\n"
+ " my-ext:shortdesc \"<A.B.C.D>\";\n"
+ " }\n"
+ " }\n"
+ " typedef my-enum {\n"
+ " type enumeration {\n"
+ " enum one;\n"
+ " enum two;\n"
+ " enum three;\n"
+ " }\n"
+ " }\n"
+ "}\n";
+ schema3 = "module module-a {\n"
+ " yang-version 1.1;\n"
+ " namespace \"urn:module-a\";\n"
+ " prefix mod-a;\n"
+ "\n"
+ " import module-inet {\n"
+ " prefix mod-inet;\n"
+ " }\n"
+ "\n"
+ " import my-extensions {\n"
+ " prefix my-ext;\n"
+ " }\n"
+ "\n"
+ " typedef server-address {\n"
+ " type union {\n"
+ " type mod-inet:ipv4-address {\n"
+ " my-ext:shortdesc \"<ipv4-address>\";\n"
+ " }\n"
+ " type mod-inet:domain-name {\n"
+ " my-ext:shortdesc \"<fqdn>\";\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}\n";
+ schema4 = "module main-module {\n"
+ " yang-version 1.1;\n"
+ " namespace \"urn:main-module\";\n"
+ " prefix main;\n"
+ "\n"
+ " import module-a {\n"
+ " prefix mod-a;\n"
+ " }\n"
+ "\n"
+ " import module-inet {\n"
+ " prefix mod-inet;\n"
+ " }\n"
+ "\n"
+ " import my-extensions {\n"
+ " prefix my-ext;\n"
+ " }\n"
+ "\n"
+ " container config {\n"
+ " leaf server {\n"
+ " type mod-a:server-address {\n"
+ " my-ext:shortdesc \"<server-address>\";\n"
+ " }\n"
+ " }\n"
+ "\n"
+ " leaf hostname {\n"
+ " type union {\n"
+ " type mod-inet:domain-name;\n"
+ " type string;\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "\n"
+ " leaf my-leaf {\n"
+ " type mod-inet:my-enum {\n"
+ " my-ext:shortdesc \"my enum\";\n"
+ " }\n"
+ " }\n"
+ "}\n";
+
+ assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, schema1, LYS_IN_YANG, NULL));
+ assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, schema2, LYS_IN_YANG, NULL));
+ assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, schema3, LYS_IN_YANG, NULL));
+ assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, schema4, LYS_IN_YANG, &mod));
+
+ /* server */
+ snode = lys_find_path(UTEST_LYCTX, NULL, "/main-module:config/server", 0);
+ assert_non_null(snode);
+
+ type = ((struct lysc_node_leaf *)snode)->type;
+ assert_int_equal(LY_ARRAY_COUNT(type->exts), 1);
+ assert_string_equal(type->exts[0].argument, "<server-address>");
+ type_u = (struct lysc_type_union *)type;
+ assert_int_equal(LY_ARRAY_COUNT(type_u->types), 2);
+
+ type = type_u->types[0];
+ assert_int_equal(LY_ARRAY_COUNT(type->exts), 2);
+ assert_string_equal(type->exts[0].argument, "<A.B.C.D>");
+ assert_string_equal(type->exts[1].argument, "<ipv4-address>");
+
+ type = type_u->types[1];
+ assert_int_equal(LY_ARRAY_COUNT(type->exts), 2);
+ assert_string_equal(type->exts[0].argument, "<host-name>");
+ assert_string_equal(type->exts[1].argument, "<fqdn>");
+
+ /* hostname */
+ snode = lys_find_path(UTEST_LYCTX, NULL, "/main-module:config/hostname", 0);
+ assert_non_null(snode);
+ type = ((struct lysc_node_leaf *)snode)->type;
+ assert_int_equal(LY_ARRAY_COUNT(type->exts), 0);
+ type_u = (struct lysc_type_union *)type;
+ assert_int_equal(LY_ARRAY_COUNT(type_u->types), 2);
+
+ type = type_u->types[0];
+ assert_int_equal(LY_ARRAY_COUNT(type->exts), 1);
+ assert_string_equal(type->exts[0].argument, "<host-name>");
+
+ type = type_u->types[1];
+ assert_int_equal(LY_ARRAY_COUNT(type->exts), 0);
+}
+
+static void
test_status(void **state)
{
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa;"
"container c {status deprecated; leaf l {status current; type string;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Status \"current\" of \"l\" is in conflict with \"deprecated\" status of parent \"c\".", "/aa:c/l");
+ CHECK_LOG_CTX("Status \"current\" of \"l\" is in conflict with \"deprecated\" status of parent \"c\".", "Path \"/aa:c/l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module bb {namespace urn:bb;prefix bb;"
"container c {status obsolete; leaf l {status current; type string;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Status \"current\" of \"l\" is in conflict with \"obsolete\" status of parent \"c\".", "/bb:c/l");
+ CHECK_LOG_CTX("Status \"current\" of \"l\" is in conflict with \"obsolete\" status of parent \"c\".", "Path \"/bb:c/l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module cc {namespace urn:cc;prefix cc;"
"container c {status obsolete; leaf l {status deprecated; type string;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Status \"deprecated\" of \"l\" is in conflict with \"obsolete\" status of parent \"c\".", "/cc:c/l");
+ CHECK_LOG_CTX("Status \"deprecated\" of \"l\" is in conflict with \"obsolete\" status of parent \"c\".", "Path \"/cc:c/l\".");
/* just a warning */
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module cc {namespace urn:dd;prefix d;"
@@ -2344,11 +2471,12 @@ test_grouping(void **state)
/* invalid - error in a non-instantiated grouping */
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa;"
"grouping grp {leaf x {type leafref;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Missing path substatement for leafref type.", "/aa:{grouping='grp'}/x");
- UTEST_LOG_CLEAN;
+ CHECK_LOG_CTX("Missing path substatement for leafref type.", "Path \"/aa:{grouping='grp'}/x\".");
+
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa;"
"container a {grouping grp {leaf x {type leafref;}}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Missing path substatement for leafref type.", "/aa:a/{grouping='grp'}/x");
+ CHECK_LOG_CTX("Missing path substatement for leafref type.", "Path \"/aa:a/{grouping='grp'}/x\".");
+ CHECK_LOG_CTX("Locally scoped grouping \"grp\" not used.", NULL);
/* config check */
ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "module z1 {namespace urn:z1;prefix z1;"
@@ -2519,52 +2647,53 @@ test_uses(void **state)
/* invalid */
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa;uses missinggrp;}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Grouping \"missinggrp\" referenced by a uses statement not found.", "/aa:{uses='missinggrp'}");
+ CHECK_LOG_CTX("Grouping \"missinggrp\" referenced by a uses statement not found.", "Path \"/aa:{uses='missinggrp'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module bb {namespace urn:bb;prefix bb;uses grp;"
"grouping grp {leaf a{type string;}uses grp1;}"
"grouping grp1 {leaf b {type string;}uses grp2;}"
"grouping grp2 {leaf c {type string;}uses grp;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Grouping \"grp\" references itself through a uses statement.", "/bb:{uses='grp'}/{uses='grp1'}/{uses='grp2'}/{uses='grp'}");
+ CHECK_LOG_CTX("Grouping \"grp\" references itself through a uses statement.", "Path \"/bb:{uses='grp'}/{uses='grp1'}/{uses='grp2'}/{uses='grp'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module cc {namespace urn:cc;prefix cc;uses a:missingprefix;}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid prefix used for grouping \"a:missingprefix\" reference.", "/cc:{uses='a:missingprefix'}");
+ CHECK_LOG_CTX("Invalid prefix used for grouping \"a:missingprefix\" reference.", "Path \"/cc:{uses='a:missingprefix'}\".");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module dd {namespace urn:dd;prefix dd;grouping grp{leaf a{type string;}}"
"leaf a {type string;}uses grp;}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Duplicate identifier \"a\" of data definition/RPC/action/notification statement.", "/dd:{uses='grp'}/dd:a");
+ CHECK_LOG_CTX("Duplicate identifier \"a\" of data definition/RPC/action/notification statement.", "Path \"/dd:{uses='grp'}/dd:a\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ee {namespace urn:ee;prefix ee;grouping grp {leaf l {type string; status deprecated;}}"
"uses grp {status obsolete;}}", LYS_IN_YANG, &mod));
CHECK_LOG_CTX("Inherited schema-only status \"obsolete\" is in conflict with \"deprecated\" status of \"l\".",
- "/ee:{uses='grp'}/ee:l");
+ "Path \"/ee:{uses='grp'}/ee:l\".");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module ff {namespace urn:ff;prefix ff;grouping grp {leaf l {type string;}}"
"leaf l {type int8;}uses grp;}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Duplicate identifier \"l\" of data definition/RPC/action/notification statement.", "/ff:{uses='grp'}/ff:l");
+ CHECK_LOG_CTX("Duplicate identifier \"l\" of data definition/RPC/action/notification statement.", "Path \"/ff:{uses='grp'}/ff:l\".");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module fg {namespace urn:fg;prefix fg;grouping grp {leaf m {type string;}}"
"uses grp;leaf m {type int8;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Duplicate identifier \"m\" of data definition/RPC/action/notification statement.", "/fg:m");
+ CHECK_LOG_CTX("Duplicate identifier \"m\" of data definition/RPC/action/notification statement.", "Path \"/fg:m\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module gg {namespace urn:gg;prefix gg; grouping grp {container g;}"
"leaf g {type string;}"
"container top {uses grp {augment /g {leaf x {type int8;}}}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid descendant-schema-nodeid value \"/g\" - name test expected instead of \"/\".", "/gg:top/{uses='grp'}/{augment='/g'}");
+ CHECK_LOG_CTX("Invalid descendant-schema-nodeid value \"/g\" - name test expected instead of \"/\".",
+ "Path \"/gg:top/{uses='grp'}/{augment='/g'}\".");
assert_int_equal(LY_ENOTFOUND, lys_parse_mem(UTEST_LYCTX, "module hh {yang-version 1.1;namespace urn:hh;prefix hh;"
"grouping grp {notification g { description \"super g\";}}"
"container top {notification h; uses grp {refine h {description \"ultra h\";}}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Refine(s) target node \"h\" in grouping \"grp\" was not found.", "/hh:top/{uses='grp'}");
+ CHECK_LOG_CTX("Refine(s) target node \"h\" in grouping \"grp\" was not found.", "Path \"/hh:top/{uses='grp'}\".");
assert_int_equal(LY_ENOTFOUND, lys_parse_mem(UTEST_LYCTX, "module ii {yang-version 1.1;namespace urn:ii;prefix ii;"
"grouping grp {action g { description \"super g\";}}"
"container top {action i; uses grp {refine i {description \"ultra i\";}}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Refine(s) target node \"i\" in grouping \"grp\" was not found.", "/ii:top/{uses='grp'}");
+ CHECK_LOG_CTX("Refine(s) target node \"i\" in grouping \"grp\" was not found.", "Path \"/ii:top/{uses='grp'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module jj {yang-version 1.1;namespace urn:jj;prefix jj;"
"grouping grp {leaf j { when \"1\"; type invalid;}}"
"container top {uses grp;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Referenced type \"invalid\" not found.", "/jj:top/{uses='grp'}/j");
+ CHECK_LOG_CTX("Referenced type \"invalid\" not found.", "Path \"/jj:top/{uses='grp'}/j\".");
}
static void
@@ -2666,65 +2795,71 @@ test_refine(void **state)
/* invalid */
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa;import grp {prefix g;}"
"uses g:grp {refine c {default hello;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid refine of container node - it is not possible to replace \"default\" property.", "/aa:{uses='g:grp'}/aa:c/{refine='c'}");
+ CHECK_LOG_CTX("Invalid refine of container node - it is not possible to replace \"default\" property.",
+ "Path \"/aa:{uses='g:grp'}/aa:c/{refine='c'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module bb {namespace urn:bb;prefix bb;import grp {prefix g;}"
"uses g:grp {refine c/l {default hello; default world;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid refine of leaf with too many (2) default properties.", "/bb:{uses='g:grp'}/bb:c/l/{refine='c/l'}");
+ CHECK_LOG_CTX("Invalid refine of leaf with too many (2) default properties.", "Path \"/bb:{uses='g:grp'}/bb:c/l/{refine='c/l'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module cc {namespace urn:cc;prefix cc;import grp {prefix g;}"
"uses g:grp {refine c/ll {default hello; default world;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid refine of default in leaf-list - the default statement is allowed only in YANG 1.1 modules.", "/cc:{uses='g:grp'}/cc:c/ll/{refine='c/ll'}");
+ CHECK_LOG_CTX("Invalid refine of default in leaf-list - the default statement is allowed only in YANG 1.1 modules.",
+ "Path \"/cc:{uses='g:grp'}/cc:c/ll/{refine='c/ll'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module dd {namespace urn:dd;prefix dd;import grp {prefix g;}"
"uses g:grp {refine c/ll {mandatory true;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid refine of leaf-list node - it is not possible to replace \"mandatory\" property.", "/dd:{uses='g:grp'}/dd:c/ll/{refine='c/ll'}");
+ CHECK_LOG_CTX("Invalid refine of leaf-list node - it is not possible to replace \"mandatory\" property.",
+ "Path \"/dd:{uses='g:grp'}/dd:c/ll/{refine='c/ll'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ee {namespace urn:ee;prefix ee;import grp {prefix g;}"
"uses g:grp {refine c/l {mandatory true;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/ee:{uses='g:grp'}/ee:c/l",
- "Invalid mandatory leaf with a default value.", "/ee:{uses='g:grp'}/ee:c/l");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/ee:{uses='g:grp'}/ee:c/l\".");
+ CHECK_LOG_CTX("Invalid mandatory leaf with a default value.", "Path \"/ee:{uses='g:grp'}/ee:c/l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ef {namespace urn:ef;prefix ef;import grp {prefix g;}"
"uses g:grp {refine c/ch {mandatory true;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/ef:{uses='g:grp'}/ef:c/ch",
- "Invalid mandatory choice with a default case.", "/ef:{uses='g:grp'}/ef:c/ch");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/ef:{uses='g:grp'}/ef:c/ch\".");
+ CHECK_LOG_CTX("Invalid mandatory choice with a default case.", "Path \"/ef:{uses='g:grp'}/ef:c/ch\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ff {namespace urn:ff;prefix ff;import grp {prefix g;}"
"uses g:grp {refine c/ch/ca/ca {mandatory true;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Mandatory node \"ca\" under the default case \"ca\".", "/ff:{uses='g:grp'}/ff:c/ch");
+ CHECK_LOG_CTX("Mandatory node \"ca\" under the default case \"ca\".", "Path \"/ff:{uses='g:grp'}/ff:c/ch\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module gg {namespace urn:gg;prefix gg;import grp {prefix g;}"
"uses g:grp {refine c/x {default hello;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/gg:{uses='g:grp'}/gg:c/x",
- "Invalid mandatory leaf with a default value.", "/gg:{uses='g:grp'}/gg:c/x");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/gg:{uses='g:grp'}/gg:c/x\".");
+ CHECK_LOG_CTX("Invalid mandatory leaf with a default value.", "Path \"/gg:{uses='g:grp'}/gg:c/x\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module hh {namespace urn:hh;prefix hh;import grp {prefix g;}"
"uses g:grp {refine c/c/l {config true;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/hh:{uses='g:grp'}/hh:c/c/l",
- "Configuration node cannot be child of any state data node.", "/hh:{uses='g:grp'}/hh:c/c/l");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/hh:{uses='g:grp'}/hh:c/c/l\".");
+ CHECK_LOG_CTX("Configuration node cannot be child of any state data node.", "Path \"/hh:{uses='g:grp'}/hh:c/c/l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ii {namespace urn:ii;prefix ii;grouping grp {leaf l {type string; status deprecated;}}"
"uses grp {status obsolete;}}", LYS_IN_YANG, &mod));
CHECK_LOG_CTX("Inherited schema-only status \"obsolete\" is in conflict with \"deprecated\" status of \"l\".",
- "/ii:{uses='grp'}/ii:l");
+ "Path \"/ii:{uses='grp'}/ii:l\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module jj {namespace urn:jj;prefix jj;import grp {prefix g;}"
"uses g:grp {refine c/x {presence nonsence;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid refine of leaf node - it is not possible to replace \"presence\" property.", "/jj:{uses='g:grp'}/jj:c/x/{refine='c/x'}");
+ CHECK_LOG_CTX("Invalid refine of leaf node - it is not possible to replace \"presence\" property.",
+ "Path \"/jj:{uses='g:grp'}/jj:c/x/{refine='c/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module kk {namespace urn:kk;prefix kk;import grp {prefix g;}"
"uses g:grp {refine c/ch {must 1;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid refine of choice node - it is not possible to add \"must\" property.", "/kk:{uses='g:grp'}/kk:c/ch/{refine='c/ch'}");
+ CHECK_LOG_CTX("Invalid refine of choice node - it is not possible to add \"must\" property.",
+ "Path \"/kk:{uses='g:grp'}/kk:c/ch/{refine='c/ch'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ll {namespace urn:ll;prefix ll;import grp {prefix g;}"
"uses g:grp {refine c/x {min-elements 1;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid refine of leaf node - it is not possible to replace \"min-elements\" property.", "/ll:{uses='g:grp'}/ll:c/x/{refine='c/x'}");
+ CHECK_LOG_CTX("Invalid refine of leaf node - it is not possible to replace \"min-elements\" property.",
+ "Path \"/ll:{uses='g:grp'}/ll:c/x/{refine='c/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module mm {namespace urn:mm;prefix mm;import grp {prefix g;}"
"uses g:grp {refine c/ll {min-elements 1;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/mm:{uses='g:grp'}/mm:c/ll",
- "The default statement is present on leaf-list with a nonzero min-elements.", "/mm:{uses='g:grp'}/mm:c/ll");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/mm:{uses='g:grp'}/mm:c/ll\".");
+ CHECK_LOG_CTX("The default statement is present on leaf-list with a nonzero min-elements.", "Path \"/mm:{uses='g:grp'}/mm:c/ll\".");
}
static void
@@ -2867,40 +3002,41 @@ test_augment(void **state)
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; container c {leaf a {type string;}}"
"augment /x/ {leaf a {type int8;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid absolute-schema-nodeid value \"/x/\" - unexpected end of expression.", "/aa:{augment='/x/'}");
+ CHECK_LOG_CTX("Invalid absolute-schema-nodeid value \"/x/\" - unexpected end of expression.", "Path \"/aa:{augment='/x/'}\".");
assert_int_equal(LY_ENOTFOUND, lys_parse_mem(UTEST_LYCTX, "module aa {namespace urn:aa;prefix aa; container c {leaf a {type string;}}"
"augment /x {leaf a {type int8;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Augment target node \"/x\" from module \"aa\" was not found.", "/aa:{augment='/x'}");
+ CHECK_LOG_CTX("Augment target node \"/x\" from module \"aa\" was not found.", "Path \"/aa:{augment='/x'}\".");
assert_int_equal(LY_EEXIST, lys_parse_mem(UTEST_LYCTX, "module bb {namespace urn:bb;prefix bb; container c {leaf a {type string;}}"
"augment /c {leaf a {type int8;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Duplicate identifier \"a\" of data definition/RPC/action/notification statement.", "/bb:{augment='/c'}/a");
+ CHECK_LOG_CTX("Duplicate identifier \"a\" of data definition/RPC/action/notification statement.", "Path \"/bb:{augment='/c'}/a\".");
assert_int_equal(LY_ENOTFOUND, lys_parse_mem(UTEST_LYCTX, "module cc {namespace urn:cc;prefix cc; container c {leaf a {type string;}}"
"augment /c/a {leaf a {type int8;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Augment target node \"/c/a\" from module \"cc\" was not found.", "/cc:{augment='/c/a'}");
+ CHECK_LOG_CTX("Augment target node \"/c/a\" from module \"cc\" was not found.", "Path \"/cc:{augment='/c/a'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module dd {namespace urn:dd;prefix dd; container c {leaf a {type string;}}"
"augment /c {case b {leaf d {type int8;}}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid augment of container node which is not allowed to contain case node \"b\".", "/dd:{augment='/c'}");
+ CHECK_LOG_CTX("Invalid augment of container node which is not allowed to contain case node \"b\".", "Path \"/dd:{augment='/c'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ee {namespace urn:ee;prefix ee; import himp {prefix hi;}"
"augment /hi:top {container c {leaf d {mandatory true; type int8;}}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid augment adding mandatory node \"c\" without making it conditional via when statement.", "/ee:{augment='/hi:top'}");
+ CHECK_LOG_CTX("Invalid augment adding mandatory node \"c\" without making it conditional via when statement.", "Path \"/ee:{augment='/hi:top'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ff {namespace urn:ff;prefix ff; container top;"
"augment ../top {leaf x {type int8;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid absolute-schema-nodeid value \"../top\" - \"/\" expected instead of \"..\".", "/ff:{augment='../top'}");
+ CHECK_LOG_CTX("Invalid absolute-schema-nodeid value \"../top\" - \"/\" expected instead of \"..\".", "Path \"/ff:{augment='../top'}\".");
assert_int_equal(LY_ENOTFOUND, lys_parse_mem(UTEST_LYCTX, "module gg {namespace urn:gg;prefix gg; rpc func;"
"augment /func {leaf x {type int8;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Augment target node \"/func\" from module \"gg\" was not found.", "/gg:{augment='/func'}");
+ CHECK_LOG_CTX("Augment target node \"/func\" from module \"gg\" was not found.", "Path \"/gg:{augment='/func'}\".");
assert_int_equal(LY_ENOTFOUND, lys_parse_mem(UTEST_LYCTX, "module hh {namespace urn:hh;prefix hh;import himp {prefix hi;}"
"augment /hi:func/input {leaf x {type string;}}"
"augment /hi:func/output {leaf y {type string;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Augment target node \"/hi:func/input\" from module \"hh\" was not found.", "/hh:{augment='/hi:func/input'}");
+ CHECK_LOG_CTX("Augment target node \"/hi:func/input\" from module \"hh\" was not found.", "Path \"/hh:{augment='/hi:func/input'}\".");
+ CHECK_LOG_CTX("Augment target node \"/hi:func/output\" from module \"hh\" was not found.", "Path \"/hh:{augment='/hi:func/output'}\".");
}
static void
@@ -3104,18 +3240,18 @@ test_deviation(void **state)
assert_true(node->flags & LYS_CONFIG_R);
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module l {namespace urn:l;prefix l; leaf a {config false; type string;}"
- "container top {config false; leaf x {type string;}}"
+ "container top {leaf x {type string;}}"
"deviation /a {deviate replace {config true;}}"
- "deviation /top {deviate replace {config true;}}}", LYS_IN_YANG, &mod));
+ "deviation /top {deviate replace {config false;}}}", LYS_IN_YANG, &mod));
assert_non_null(node = mod->compiled->data);
assert_string_equal("a", node->name);
assert_true(node->flags & LYS_CONFIG_W);
assert_non_null(node = node->next);
assert_string_equal("top", node->name);
- assert_true(node->flags & LYS_CONFIG_W);
+ assert_true(node->flags & LYS_CONFIG_R);
assert_non_null(node = lysc_node_child(node));
assert_string_equal("x", node->name);
- assert_true(node->flags & LYS_CONFIG_W);
+ assert_true(node->flags & LYS_CONFIG_R);
assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module m {namespace urn:m;prefix m;"
"container a {leaf a {type string;}}"
@@ -3356,194 +3492,199 @@ test_deviation(void **state)
assert_int_equal(LY_ENOTFOUND, lys_parse_mem(UTEST_LYCTX, "module aa1 {namespace urn:aa1;prefix aa1;import a {prefix a;}"
"deviation /a:top/a:z {deviate not-supported;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Deviation(s) target node \"/a:top/a:z\" from module \"aa1\" was not found.", "/a:{deviation='/a:top/a:z'}");
+ CHECK_LOG_CTX("Deviation(s) target node \"/a:top/a:z\" from module \"aa1\" was not found.", "Path \"/a:{deviation='/a:top/a:z'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module aa2 {namespace urn:aa2;prefix aa2;import a {prefix a;}"
"deviation /a:top/a:a {deviate not-supported;}"
"deviation /a:top/a:a {deviate add {default error;}}}", LYS_IN_YANG, NULL));
- CHECK_LOG_CTX("Multiple deviations of \"/a:top/a:a\" with one of them being \"not-supported\".", "/aa2:{deviation='/a:top/a:a'}");
+ CHECK_LOG_CTX("Multiple deviations of \"/a:top/a:a\" with one of them being \"not-supported\".", "Path \"/aa2:{deviation='/a:top/a:a'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module bb {namespace urn:bb;prefix bb;import a {prefix a;}"
"deviation a:top/a:a {deviate not-supported;}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid absolute-schema-nodeid value \"a:top/a:a\" - \"/\" expected instead of \"a:top\".", "/bb:{deviation='a:top/a:a'}");
+ CHECK_LOG_CTX("Invalid absolute-schema-nodeid value \"a:top/a:a\" - \"/\" expected instead of \"a:top\".", "Path \"/bb:{deviation='a:top/a:a'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module cc {namespace urn:cc;prefix cc; container c;"
"deviation /c {deviate add {units meters;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation of container node - it is not possible to add \"units\" property.", "/cc:{deviation='/c'}");
+ CHECK_LOG_CTX("Invalid deviation of container node - it is not possible to add \"units\" property.", "Path \"/cc:{deviation='/c'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module cd {namespace urn:cd;prefix cd; leaf c {type string; units centimeters;}"
"deviation /c {deviate add {units meters;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation adding \"units\" property which already exists (with value \"centimeters\").", "/cd:{deviation='/c'}");
+ CHECK_LOG_CTX("Invalid deviation adding \"units\" property which already exists (with value \"centimeters\").", "Path \"/cd:{deviation='/c'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module dd1 {namespace urn:dd1;prefix dd1; container c;"
"deviation /c {deviate delete {units meters;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation of container node - it is not possible to delete \"units\" property.", "/dd1:{deviation='/c'}");
+ CHECK_LOG_CTX("Invalid deviation of container node - it is not possible to delete \"units\" property.", "Path \"/dd1:{deviation='/c'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module dd2 {namespace urn:dd2;prefix dd2; leaf c {type string;}"
"deviation /c {deviate delete {units meters;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation deleting \"units\" property \"meters\" which is not present.", "/dd2:{deviation='/c'}");
+ CHECK_LOG_CTX("Invalid deviation deleting \"units\" property \"meters\" which is not present.", "Path \"/dd2:{deviation='/c'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module dd3 {namespace urn:dd3;prefix dd3; leaf c {type string; units centimeters;}"
"deviation /c {deviate delete {units meters;}}}", LYS_IN_YANG, &mod));
CHECK_LOG_CTX("Invalid deviation deleting \"units\" property \"meters\" which does not match the target's property value \"centimeters\".",
- "/dd3:{deviation='/c'}");
+ "Path \"/dd3:{deviation='/c'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ee1 {namespace urn:ee1;prefix ee1; container c;"
"deviation /c {deviate replace {units meters;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation of container node - it is not possible to replace \"units\" property.", "/ee1:{deviation='/c'}");
+ CHECK_LOG_CTX("Invalid deviation of container node - it is not possible to replace \"units\" property.", "Path \"/ee1:{deviation='/c'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ee2 {namespace urn:ee2;prefix ee2; leaf c {type string;}"
"deviation /c {deviate replace {units meters;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation replacing \"units\" property \"meters\" which is not present.", "/ee2:{deviation='/c'}");
+ CHECK_LOG_CTX("Invalid deviation replacing \"units\" property \"meters\" which is not present.", "Path \"/ee2:{deviation='/c'}\".");
/* the default is already deleted in /e:a byt module f */
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ff1 {namespace urn:ff1;prefix ff1; import e {prefix e;}"
"deviation /e:a {deviate delete {default x:aa;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation deleting \"default\" property \"x:aa\" which is not present.", "/ff1:{deviation='/e:a'}");
+ CHECK_LOG_CTX("Invalid deviation deleting \"default\" property \"x:aa\" which is not present.", "Path \"/ff1:{deviation='/e:a'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ff3 {namespace urn:ff3;prefix ff3; import e {prefix e;}"
"deviation /e:b {deviate delete {default e:b;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation deleting \"default\" property \"e:b\" which does not match the target's property value \"x:ba\".", "/ff3:{deviation='/e:b'}");
+ CHECK_LOG_CTX("Invalid deviation deleting \"default\" property \"e:b\" which does not match the target's property value \"x:ba\".",
+ "Path \"/ff3:{deviation='/e:b'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ff5 {namespace urn:ff5;prefix ff5; anyxml a;"
"deviation /a {deviate delete {default x;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation of anyxml node - it is not possible to delete \"default\" property.", "/ff5:{deviation='/a'}");
+ CHECK_LOG_CTX("Invalid deviation of anyxml node - it is not possible to delete \"default\" property.", "Path \"/ff5:{deviation='/a'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ff6 {namespace urn:ff6;prefix ff6; import e {prefix e;}"
"deviation /e:c {deviate delete {default hi;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation deleting \"default\" property \"hi\" which does not match the target's property value \"hello\".", "/ff6:{deviation='/e:c'}");
+ CHECK_LOG_CTX("Invalid deviation deleting \"default\" property \"hi\" which does not match the target's property value \"hello\".",
+ "Path \"/ff6:{deviation='/e:c'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ff7 {namespace urn:ff7;prefix ff7; import e {prefix e;}"
"deviation /e:d {deviate delete {default hi;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation deleting \"default\" property \"hi\" which does not match any of the target's property values.", "/ff7:{deviation='/e:d'}");
+ CHECK_LOG_CTX("Invalid deviation deleting \"default\" property \"hi\" which does not match any of the target's property values.",
+ "Path \"/ff7:{deviation='/e:d'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module gg1 {namespace urn:gg1;prefix gg1; import e {prefix e;}"
"deviation /e:b {deviate add {default e:a;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation adding \"default\" property which already exists (with value \"x:ba\").", "/gg1:{deviation='/e:b'}");
+ CHECK_LOG_CTX("Invalid deviation adding \"default\" property which already exists (with value \"x:ba\").", "Path \"/gg1:{deviation='/e:b'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module gg2 {namespace urn:gg2;prefix gg2; import e {prefix e;}"
"deviation /e:a {deviate add {default x:a;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/e:a",
- "Default case prefix \"x\" not found in imports of \"gg2\".", "/e:a");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/e:a\".");
+ CHECK_LOG_CTX("Default case prefix \"x\" not found in imports of \"gg2\".", "Path \"/e:a\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module gg3 {namespace urn:gg3;prefix gg3; import e {prefix e;}"
"deviation /e:a {deviate add {default a;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/e:a",
- "Default case \"a\" not found.", "/e:a");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/e:a\".");
+ CHECK_LOG_CTX("Default case \"a\" not found.", "Path \"/e:a\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module gg4 {namespace urn:gg4;prefix gg4; import e {prefix e;}"
"deviation /e:c {deviate add {default hi;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation adding \"default\" property which already exists (with value \"hello\").", "/gg4:{deviation='/e:c'}");
+ CHECK_LOG_CTX("Invalid deviation adding \"default\" property which already exists (with value \"hello\").", "Path \"/gg4:{deviation='/e:c'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module gg4 {namespace urn:gg4;prefix gg4; import e {prefix e;}"
"deviation /e:a {deviate add {default e:ac;}}}", LYS_IN_YANG, &mod));
- /*CHECK_LOG_CTX("Invalid deviation adding \"default\" property \"e:ac\" of choice - mandatory node \"ac\" under the default case.", "/gg4:{deviation='/e:a'}");*/
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/e:a");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/e:a\".");
+ CHECK_LOG_CTX("Mandatory node \"ac\" under the default case \"e:ac\".", "Path \"/e:a\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module gg5 {namespace urn:gg5;prefix gg5; leaf x {type string; mandatory true;}"
"deviation /x {deviate add {default error;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/gg5:{deviation='/x'}",
- "Invalid mandatory leaf with a default value.", "/gg5:{deviation='/x'}");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/gg5:{deviation='/x'}\".");
+ CHECK_LOG_CTX("Invalid mandatory leaf with a default value.", "Path \"/gg5:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module hh1 {yang-version 1.1; namespace urn:hh1;prefix hh1; import e {prefix e;}"
"deviation /e:d {deviate replace {default hi;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation of leaf-list node - it is not possible to replace \"default\" property.", "/hh1:{deviation='/e:d'}");
+ CHECK_LOG_CTX("Invalid deviation of leaf-list node - it is not possible to replace \"default\" property.",
+ "Path \"/hh1:{deviation='/e:d'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ii1 {namespace urn:ii1;prefix ii1; import i {prefix i;}"
"deviation /i:l1 {deviate delete {unique x;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation deleting \"unique\" property \"x\" which does not match any of the target's property values.", "/ii1:{deviation='/i:l1'}");
+ CHECK_LOG_CTX("Invalid deviation deleting \"unique\" property \"x\" which does not match any of the target's property values.",
+ "Path \"/ii1:{deviation='/i:l1'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ii2 {namespace urn:ii2;prefix ii2; import i {prefix i;} leaf x { type string;}"
"deviation /i:l2 {deviate delete {unique d;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation deleting \"unique\" property \"d\" which does not match any of the target's property values.", "/ii2:{deviation='/i:l2'}");
+ CHECK_LOG_CTX("Invalid deviation deleting \"unique\" property \"d\" which does not match any of the target's property values.",
+ "Path \"/ii2:{deviation='/i:l2'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ii3 {namespace urn:ii3;prefix ii3; leaf x { type string;}"
"deviation /x {deviate delete {unique d;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation of leaf node - it is not possible to delete \"unique\" property.", "/ii3:{deviation='/x'}");
+ CHECK_LOG_CTX("Invalid deviation of leaf node - it is not possible to delete \"unique\" property.", "Path \"/ii3:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ii4 {namespace urn:ii4;prefix ii4; leaf x { type string;}"
"deviation /x {deviate add {unique d;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation of leaf node - it is not possible to add \"unique\" property.", "/ii4:{deviation='/x'}");
+ CHECK_LOG_CTX("Invalid deviation of leaf node - it is not possible to add \"unique\" property.", "Path \"/ii4:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module jj1 {namespace urn:jj1;prefix jj1; choice ch {case a {leaf a{type string;}}}"
"deviation /ch/a {deviate add {config false;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation of case node - it is not possible to add \"config\" property.", "/jj1:{deviation='/ch/a'}");
+ CHECK_LOG_CTX("Invalid deviation of case node - it is not possible to add \"config\" property.", "Path \"/jj1:{deviation='/ch/a'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module jj2 {namespace urn:jj2;prefix jj2; container top {config false; leaf x {type string;}}"
"deviation /top/x {deviate add {config true;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/jj2:{deviation='/top/x'}",
- "Configuration node cannot be child of any state data node.", "/jj2:{deviation='/top/x'}");
- assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module jj3 {namespace urn:jj3;prefix jj3; container top {leaf x {type string;}}"
- "deviation /top/x {deviate replace {config false;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation replacing \"config\" property \"config false\" which is not present.", "/jj3:{deviation='/top/x'}");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/jj2:{deviation='/top/x'}\".");
+ CHECK_LOG_CTX("Configuration node cannot be child of any state data node.", "Path \"/jj2:{deviation='/top/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module jj4 {namespace urn:jj4;prefix jj4; choice ch {case a {leaf a{type string;}}}"
"deviation /ch/a {deviate replace {config false;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation of case node - it is not possible to replace \"config\" property.", "/jj4:{deviation='/ch/a'}");
+ CHECK_LOG_CTX("Invalid deviation of case node - it is not possible to replace \"config\" property.", "Path \"/jj4:{deviation='/ch/a'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module jj5 {namespace urn:jj5;prefix jj5; container top {leaf x {type string; config true;}}"
"deviation /top {deviate add {config false;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/jj5:top",
- "Configuration node cannot be child of any state data node.", "/jj5:top/x");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/jj5:top\".");
+ CHECK_LOG_CTX("Configuration node cannot be child of any state data node.", "Path \"/jj5:top/x\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module jj6 {namespace urn:jj6;prefix jj6; leaf x {config false; type string;}"
"deviation /x {deviate add {config true;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation adding \"config\" property which already exists (with value \"config false\").", "/jj6:{deviation='/x'}");
+ CHECK_LOG_CTX("Invalid deviation adding \"config\" property which already exists (with value \"config false\").",
+ "Path \"/jj6:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module kk1 {namespace urn:kk1;prefix kk1; container top {leaf a{type string;}}"
"deviation /top {deviate add {mandatory true;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation of container node - it is not possible to add \"mandatory\" property.", "/kk1:{deviation='/top'}");
+ CHECK_LOG_CTX("Invalid deviation of container node - it is not possible to add \"mandatory\" property.", "Path \"/kk1:{deviation='/top'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module kk2 {namespace urn:kk2;prefix kk2; container top {leaf a{type string;}}"
"deviation /top {deviate replace {mandatory true;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation of container node - it is not possible to replace \"mandatory\" property.", "/kk2:{deviation='/top'}");
+ CHECK_LOG_CTX("Invalid deviation of container node - it is not possible to replace \"mandatory\" property.", "Path \"/kk2:{deviation='/top'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module kk3 {namespace urn:kk3;prefix kk3; container top {leaf x {type string;}}"
"deviation /top/x {deviate replace {mandatory true;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation replacing \"mandatory\" property \"mandatory true\" which is not present.", "/kk3:{deviation='/top/x'}");
+ CHECK_LOG_CTX("Invalid deviation replacing \"mandatory\" property \"mandatory true\" which is not present.", "Path \"/kk3:{deviation='/top/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module kk4 {namespace urn:kk4;prefix kk4; leaf x {mandatory true; type string;}"
"deviation /x {deviate add {mandatory false;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation adding \"mandatory\" property which already exists (with value \"mandatory true\").", "/kk4:{deviation='/x'}");
+ CHECK_LOG_CTX("Invalid deviation adding \"mandatory\" property which already exists (with value \"mandatory true\").",
+ "Path \"/kk4:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ll1 {namespace urn:ll1;prefix ll1; leaf x {default test; type string;}"
"deviation /x {deviate add {mandatory true;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/ll1:{deviation='/x'}",
- "Invalid mandatory leaf with a default value.", "/ll1:{deviation='/x'}");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/ll1:{deviation='/x'}\".");
+ CHECK_LOG_CTX("Invalid mandatory leaf with a default value.", "Path \"/ll1:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ll2 {yang-version 1.1; namespace urn:ll2;prefix ll2; leaf-list x {default test; type string;}"
"deviation /x {deviate add {min-elements 1;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/ll2:{deviation='/x'}",
- "The default statement is present on leaf-list with a nonzero min-elements.", "/ll2:{deviation='/x'}");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/ll2:{deviation='/x'}\".");
+ CHECK_LOG_CTX("The default statement is present on leaf-list with a nonzero min-elements.", "Path \"/ll2:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module ll2 {namespace urn:ll2;prefix ll2; choice ch {default a; leaf a {type string;} leaf b {type string;}}"
"deviation /ch {deviate add {mandatory true;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/ll2:ch",
- "Invalid mandatory choice with a default case.", "/ll2:ch");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/ll2:ch\".");
+ CHECK_LOG_CTX("Invalid mandatory choice with a default case.", "Path \"/ll2:ch\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module mm1 {namespace urn:mm1;prefix mm1; leaf-list x {min-elements 10; type string;}"
"deviation /x {deviate add {max-elements 5;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/mm1:{deviation='/x'}",
- "Leaf-list min-elements 10 is bigger than max-elements 5.", "/mm1:{deviation='/x'}");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/mm1:{deviation='/x'}\".");
+ CHECK_LOG_CTX("Leaf-list min-elements 10 is bigger than max-elements 5.", "Path \"/mm1:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module mm2 {namespace urn:mm2;prefix mm2; leaf-list x {max-elements 10; type string;}"
"deviation /x {deviate add {min-elements 20;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/mm2:{deviation='/x'}",
- "Leaf-list min-elements 20 is bigger than max-elements 10.", "/mm2:{deviation='/x'}");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/mm2:{deviation='/x'}\".");
+ CHECK_LOG_CTX("Leaf-list min-elements 20 is bigger than max-elements 10.", "Path \"/mm2:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module mm3 {namespace urn:mm3;prefix mm3; list x {min-elements 5; max-elements 10; config false;}"
"deviation /x {deviate replace {max-elements 1;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/mm3:{deviation='/x'}",
- "List min-elements 5 is bigger than max-elements 1.", "/mm3:{deviation='/x'}");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/mm3:{deviation='/x'}\".");
+ CHECK_LOG_CTX("List min-elements 5 is bigger than max-elements 1.", "Path \"/mm3:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module mm4 {namespace urn:mm4;prefix mm4; list x {min-elements 5; max-elements 10; config false;}"
"deviation /x {deviate replace {min-elements 20;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/mm4:{deviation='/x'}",
- "List min-elements 20 is bigger than max-elements 10.", "/mm4:{deviation='/x'}");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/mm4:{deviation='/x'}\".");
+ CHECK_LOG_CTX("List min-elements 20 is bigger than max-elements 10.", "Path \"/mm4:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module mm5 {namespace urn:mm5;prefix mm5; leaf-list x {type string; min-elements 5;}"
"deviation /x {deviate add {min-elements 1;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation adding \"min-elements\" property which already exists (with value \"5\").", "/mm5:{deviation='/x'}");
+ CHECK_LOG_CTX("Invalid deviation adding \"min-elements\" property which already exists (with value \"5\").", "Path \"/mm5:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module mm6 {namespace urn:mm6;prefix mm6; list x {config false; min-elements 5;}"
"deviation /x {deviate add {min-elements 1;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation adding \"min-elements\" property which already exists (with value \"5\").", "/mm6:{deviation='/x'}");
+ CHECK_LOG_CTX("Invalid deviation adding \"min-elements\" property which already exists (with value \"5\").", "Path \"/mm6:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module mm7 {namespace urn:mm7;prefix mm7; leaf-list x {type string; max-elements 5;}"
"deviation /x {deviate add {max-elements 1;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation adding \"max-elements\" property which already exists (with value \"5\").", "/mm7:{deviation='/x'}");
+ CHECK_LOG_CTX("Invalid deviation adding \"max-elements\" property which already exists (with value \"5\").", "Path \"/mm7:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module mm8 {namespace urn:mm8;prefix mm8; list x {config false; max-elements 5;}"
"deviation /x {deviate add {max-elements 1;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation adding \"max-elements\" property which already exists (with value \"5\").", "/mm8:{deviation='/x'}");
+ CHECK_LOG_CTX("Invalid deviation adding \"max-elements\" property which already exists (with value \"5\").", "Path \"/mm8:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module mm9 {namespace urn:mm9;prefix mm9; leaf-list x {type string;}"
"deviation /x {deviate replace {min-elements 1;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation replacing \"min-elements\" property which is not present.", "/mm9:{deviation='/x'}");
+ CHECK_LOG_CTX("Invalid deviation replacing \"min-elements\" property which is not present.", "Path \"/mm9:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module mm10 {namespace urn:mm10;prefix mm10; list x {config false;}"
"deviation /x {deviate replace {min-elements 1;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation replacing \"min-elements\" property which is not present.", "/mm10:{deviation='/x'}");
+ CHECK_LOG_CTX("Invalid deviation replacing \"min-elements\" property which is not present.", "Path \"/mm10:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module mm11 {namespace urn:mm11;prefix mm11; leaf-list x {type string;}"
"deviation /x {deviate replace {max-elements 1;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation replacing \"max-elements\" property which is not present.", "/mm11:{deviation='/x'}");
+ CHECK_LOG_CTX("Invalid deviation replacing \"max-elements\" property which is not present.", "Path \"/mm11:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module mm12 {namespace urn:mm12;prefix mm12; list x {config false; }"
"deviation /x {deviate replace {max-elements 1;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation replacing \"max-elements\" property which is not present.", "/mm12:{deviation='/x'}");
+ CHECK_LOG_CTX("Invalid deviation replacing \"max-elements\" property which is not present.", "Path \"/mm12:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module nn1 {namespace urn:nn1;prefix nn1; anyxml x;"
"deviation /x {deviate replace {type string;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Invalid deviation of anyxml node - it is not possible to replace \"type\" property.", "/nn1:{deviation='/x'}");
+ CHECK_LOG_CTX("Invalid deviation of anyxml node - it is not possible to replace \"type\" property.", "Path \"/nn1:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module nn2 {namespace urn:nn2;prefix nn2; leaf-list x {type string;}"
"deviation /x {deviate replace {type empty;}}}", LYS_IN_YANG, &mod));
- CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "/nn2:{deviation='/x'}",
- "Leaf-list of type \"empty\" is allowed only in YANG 1.1 modules.", "/nn2:{deviation='/x'}");
+ CHECK_LOG_CTX("Compilation of a deviated and/or refined node failed.", "Path \"/nn2:{deviation='/x'}\".");
+ CHECK_LOG_CTX("Leaf-list of type \"empty\" is allowed only in YANG 1.1 modules.", "Path \"/nn2:{deviation='/x'}\".");
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module oo1 {namespace urn:oo1;prefix oo1; leaf x {type uint16; default 300;}"
"deviation /x {deviate replace {type uint8;}}}", LYS_IN_YANG, &mod));
@@ -3563,6 +3704,7 @@ test_deviation(void **state)
assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, "module pp1 {namespace urn:pp1;prefix pp1; import pp {prefix pp;}"
"deviation /pp:c/pp:x {deviate not-supported;}}", LYS_IN_YANG, &mod));
CHECK_LOG_CTX("Target of leafref \"l\" cannot be referenced because it is disabled.", "Schema location \"/pp:l\".");
+ CHECK_LOG_CTX("Not found node \"x\" in path.", "Schema location \"/pp:l\".");
}
static void
@@ -3755,6 +3897,55 @@ test_when(void **state)
" }"
"}",
LYS_IN_YANG, NULL));
+
+ ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb,
+ "module d1 {"
+ " namespace urn:d1;"
+ " prefix d1;"
+ " container ifm {"
+ " container interfaces {"
+ " list interface {"
+ " key \"name\";"
+ " leaf name {"
+ " type string;"
+ " }"
+ " container ethernet {"
+ " container main-interface {"
+ " container l2-attribute {"
+ " when \"not(/d1:ifm/d1:interfaces/d1:interface/d1:trunk/d1:members/d1:member[d1:name=current()/../../../d1:name])\";"
+ " presence \"\";"
+ " }"
+ " }"
+ " }"
+ " container trunk {"
+ " container members {"
+ " list member {"
+ " key \"name\";"
+ " leaf name {"
+ " type string;"
+ " }"
+ " }"
+ " }"
+ " }"
+ " }"
+ " }"
+ " }"
+ "}");
+ assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX,
+ "module d2 {"
+ " namespace \"urn:d2\";"
+ " prefix d2;"
+ " import d1 {"
+ " prefix d1;"
+ " }"
+ " augment \"/d1:ifm/d1:interfaces/d1:interface/d1:ethernet/d1:main-interface\" {"
+ " when \"not(d1:l2-attribute)\";"
+ " container extra-attribute {"
+ " presence \"\";"
+ " }"
+ " }"
+ "}",
+ LYS_IN_YANG, NULL));
}
static void
@@ -3796,6 +3987,68 @@ test_must(void **state)
LYS_IN_YANG, NULL));
/* no warnings */
CHECK_LOG_CTX(NULL, NULL);
+
+ /* must referencing disabled leafref in another module */
+ ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb,
+ "module b-imp {"
+ " yang-version 1.1;"
+ " namespace \"urn:b-imp\";"
+ " prefix \"bi\";"
+ ""
+ " feature feat;"
+ ""
+ " grouping band-capabilities {"
+ " leaf band-number {"
+ " type uint16;"
+ " }"
+ ""
+ " container sub-band-info {"
+ " when \"../band-number = '46'\";"
+ " if-feature \"bi:feat\";"
+ " leaf number-of-laa-scarriers {"
+ " type uint8;"
+ " }"
+ " }"
+ " }"
+ ""
+ " container module-capability {"
+ " list band-capabilities {"
+ " key band-number;"
+ " config false;"
+ " uses band-capabilities;"
+ " }"
+ " container rw-sub-band-info {"
+ " if-feature \"bi:feat\";"
+ " leaf rw-number-of-laa-scarriers {"
+ " type leafref {"
+ " path \"/module-capability/band-capabilities/sub-band-info/number-of-laa-scarriers\";"
+ " require-instance false;"
+ " }"
+ " }"
+ " }"
+ " }"
+ "}");
+
+ ly_ctx_set_options(UTEST_LYCTX, LY_CTX_REF_IMPLEMENTED);
+ assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX,
+ "module b {"
+ " yang-version 1.1;"
+ " namespace \"urn:b\";"
+ " prefix \"b\";"
+ ""
+ " import b-imp {"
+ " prefix \"bi\";"
+ " }"
+ ""
+ " container laa-config {"
+ " must \"number-of-laa-scarriers <= /bi:module-capability/bi:rw-sub-band-info/bi:rw-number-of-laa-scarriers\";"
+ " }"
+ "}",
+ LYS_IN_YANG, NULL));
+ ly_ctx_unset_options(UTEST_LYCTX, LY_CTX_REF_IMPLEMENTED);
+
+ CHECK_LOG_CTX("Schema node \"number-of-laa-scarriers\" not found; in expr \"number-of-laa-scarriers\" "
+ "with context node \"/b:laa-config\".", NULL);
}
int
@@ -3816,6 +4069,7 @@ main(void)
UTEST(test_type_empty, setup),
UTEST(test_type_union, setup),
UTEST(test_type_dflt, setup),
+ UTEST(test_type_exts, setup),
UTEST(test_status, setup),
UTEST(test_node_container, setup),
UTEST(test_node_leaflist, setup),
diff --git a/tests/utests/schema/test_yang.c b/tests/utests/schema/test_yang.c
index 78b1798..6d1c2ae 100644
--- a/tests/utests/schema/test_yang.c
+++ b/tests/utests/schema/test_yang.c
@@ -155,6 +155,7 @@ test_helpers(void **state)
assert_int_equal(LY_EVALID, buf_store_char(YCTX, Y_IDENTIF_ARG, &p, &len, &buf, &size, 1, &prefix));
in.current = ":";
assert_int_equal(LY_EVALID, buf_store_char(YCTX, Y_IDENTIF_ARG, &p, &len, &buf, &size, 1, &prefix));
+ UTEST_LOG_CTX_CLEAN;
/* valid colon for prefixed identifiers */
len = size = 0;
p = NULL;
@@ -183,6 +184,7 @@ test_helpers(void **state)
assert_int_equal(LY_SUCCESS, lysp_check_identifierchar((struct lysp_ctx *)YCTX, ':', 0, &prefix));
assert_int_equal(1, prefix);
assert_int_equal(LY_EVALID, lysp_check_identifierchar((struct lysp_ctx *)YCTX, ':', 0, &prefix));
+ CHECK_LOG_CTX("Invalid identifier first character ':' (0x003a).", "Line number 1.");
assert_int_equal(1, prefix);
assert_int_equal(LY_SUCCESS, lysp_check_identifierchar((struct lysp_ctx *)YCTX, 'b', 0, &prefix));
assert_int_equal(2, prefix);
@@ -887,12 +889,18 @@ test_module(void **state)
ly_ctx_set_module_imp_clb(PARSER_CUR_PMOD(YCTX)->mod->ctx, test_imp_clb, "module xxx { namespace urn:xxx; prefix x;}");
in.current = "module" SCHEMA_BEGINNING "include xxx;}";
assert_int_equal(lys_parse_mem(PARSER_CUR_PMOD(YCTX)->mod->ctx, in.current, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"name\" failed.", NULL, "Including \"xxx\" submodule into \"name\" failed.", NULL);
+ CHECK_LOG_CTX("Parsing module \"name\" failed.", NULL);
+ CHECK_LOG_CTX("Including \"xxx\" submodule into \"name\" failed.", NULL);
+ CHECK_LOG_CTX("Data model \"xxx\" not found in local searchdirs.", NULL);
+ CHECK_LOG_CTX("Parsing submodule failed.", NULL);
+ CHECK_LOG_CTX("Input data contains module in situation when a submodule is expected.", NULL);
ly_ctx_set_module_imp_clb(PARSER_CUR_PMOD(YCTX)->mod->ctx, test_imp_clb, "submodule xxx {belongs-to wrong-name {prefix w;}}");
in.current = "module" SCHEMA_BEGINNING "include xxx;}";
assert_int_equal(lys_parse_mem(PARSER_CUR_PMOD(YCTX)->mod->ctx, in.current, LYS_IN_YANG, NULL), LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"name\" failed.", NULL, "Including \"xxx\" submodule into \"name\" failed.", NULL);
+ CHECK_LOG_CTX("Parsing module \"name\" failed.", NULL);
+ CHECK_LOG_CTX("Including \"xxx\" submodule into \"name\" failed.", NULL);
+ UTEST_LOG_CTX_CLEAN;
ly_ctx_set_module_imp_clb(PARSER_CUR_PMOD(YCTX)->mod->ctx, test_imp_clb, "submodule xxx {belongs-to name {prefix x;}}");
TEST_GENERIC("include xxx;}", mod->includes,
diff --git a/tests/utests/schema/test_yin.c b/tests/utests/schema/test_yin.c
index 0ce3abc..a531b64 100644
--- a/tests/utests/schema/test_yin.c
+++ b/tests/utests/schema/test_yin.c
@@ -395,11 +395,13 @@ test_validate_value(void **state)
YCTX->xmlctx->value = "pre:b";
YCTX->xmlctx->value_len = 5;
assert_int_equal(yin_validate_value(YCTX, Y_IDENTIF_ARG), LY_EVALID);
+ CHECK_LOG_CTX("Invalid identifier character ':' (0x003a).", "Line number 1.");
assert_int_equal(yin_validate_value(YCTX, Y_PREF_IDENTIF_ARG), LY_SUCCESS);
YCTX->xmlctx->value = "pre:pre:b";
YCTX->xmlctx->value_len = 9;
assert_int_equal(yin_validate_value(YCTX, Y_PREF_IDENTIF_ARG), LY_EVALID);
+ CHECK_LOG_CTX("Invalid identifier character ':' (0x003a).", "Line number 1.");
}
static void
@@ -3097,7 +3099,7 @@ test_module_elem(void **state)
assert_int_equal(yin_parse_mod(YCTX, lysp_mod), LY_SUCCESS);
assert_string_equal(lysp_mod->mod->name, "mod");
- assert_string_equal(lysp_mod->revs, "2019-02-02");
+ assert_string_equal(lysp_mod->revs[0].date, "2019-02-02");
assert_string_equal(lysp_mod->mod->ns, "ns");
assert_string_equal(lysp_mod->mod->prefix, "pref");
assert_null(lysp_mod->mod->filepath);
@@ -3230,8 +3232,10 @@ test_submodule_elem(void **state)
assert_int_equal(lyxml_ctx_new(UTEST_LYCTX, UTEST_IN, &YCTX->xmlctx), LY_SUCCESS);
assert_int_equal(yin_parse_submod(YCTX, lysp_submod), LY_SUCCESS);
+ CHECK_LOG_CTX("YANG version 1.1 expects all includes in main module, includes in submodules (mod) are not necessary.",
+ NULL);
assert_string_equal(lysp_submod->name, "mod");
- assert_string_equal(lysp_submod->revs, "2019-02-02");
+ assert_string_equal(lysp_submod->revs[0].date, "2019-02-02");
assert_string_equal(lysp_submod->prefix, "pref");
assert_null(lysp_submod->filepath);
assert_string_equal(lysp_submod->org, "org");
diff --git a/tests/utests/types/binary.c b/tests/utests/types/binary.c
index 05b6b97..4f3ea66 100644
--- a/tests/utests/types/binary.c
+++ b/tests/utests/types/binary.c
@@ -52,14 +52,15 @@ test_plugin_store(void **state)
struct lys_module *mod;
struct lyd_value value = {0};
struct lyplg_type *type = lyplg_type_plugin_find("", NULL, ly_data_type2str[LY_TYPE_BINARY]);
- struct lysc_type *lysc_type;
+ struct lysc_type *lysc_type, *lysc_type2;
LY_ERR ly_ret;
const char *schema;
/* create schema. Prepare common used variables */
- schema = MODULE_CREATE_YANG("a", "leaf l {type binary;}");
+ schema = MODULE_CREATE_YANG("a", "leaf l {type binary;} leaf k {type binary {length 4..8;}}");
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type;
+ lysc_type2 = ((struct lysc_node_leaf *)mod->compiled->data->next)->type;
/* check proper type */
assert_string_equal("libyang 2 - binary, version 1", type->id);
@@ -176,6 +177,35 @@ test_plugin_store(void **state)
assert_ptr_equal(value.realtype, lysc_type);
type->free(UTEST_LYCTX, &value);
+ /* length check */
+ val = "Zm91cg==";
+ dec_val = "four";
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type2, val, strlen(val),
+ 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err));
+ CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val));
+ assert_ptr_equal(value.realtype, lysc_type2);
+ type->free(UTEST_LYCTX, &value);
+
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type2, dec_val, strlen(dec_val),
+ 0, LY_VALUE_LYB, NULL, 0, NULL, &value, NULL, &err));
+ CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val));
+ assert_ptr_equal(value.realtype, lysc_type2);
+ type->free(UTEST_LYCTX, &value);
+
+ val = "ZWlnaHQwMTI=";
+ dec_val = "eight012";
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type2, val, strlen(val),
+ 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err));
+ CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val));
+ assert_ptr_equal(value.realtype, lysc_type2);
+ type->free(UTEST_LYCTX, &value);
+
+ assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type2, dec_val, strlen(dec_val),
+ 0, LY_VALUE_LYB, NULL, 0, NULL, &value, NULL, &err));
+ CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val));
+ assert_ptr_equal(value.realtype, lysc_type2);
+ type->free(UTEST_LYCTX, &value);
+
/*
* ERROR TESTS
*/
@@ -194,6 +224,14 @@ test_plugin_store(void **state)
assert_int_equal(LY_EVALID, ly_ret);
assert_string_equal(err->msg, "Base64 encoded value length must be divisible by 4.");
ly_err_free(err);
+
+ val = "MTIz";
+ err = NULL;
+ ly_ret = type->store(UTEST_LYCTX, lysc_type2, val, strlen(val),
+ 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err);
+ assert_int_equal(LY_EVALID, ly_ret);
+ assert_string_equal(err->msg, "Unsatisfied length - string \"MTIz\" length is not allowed.");
+ ly_err_free(err);
}
static void
diff --git a/tests/utests/types/bits.c b/tests/utests/types/bits.c
index 3d42ebc..eb40965 100644
--- a/tests/utests/types/bits.c
+++ b/tests/utests/types/bits.c
@@ -179,7 +179,7 @@ test_schema_yang(void **state)
"leaf port {type my_type {"
" bit ten {position 11;} bit two;}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Invalid bits - position of the item \"ten\" has changed from 10 to 11 in the derived type.", "/TERR_0:port");
+ CHECK_LOG_CTX("Invalid bits - position of the item \"ten\" has changed from 10 to 11 in the derived type.", "Path \"/TERR_0:port\".");
/* add new bit */
schema = MODULE_CREATE_YANG("TERR_1", "typedef my_type{type bits {"
@@ -187,15 +187,15 @@ test_schema_yang(void **state)
"leaf port {type my_type {"
" bit ten {position 10;} bit two; bit test;}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Invalid bits - derived type adds new item \"test\".", "/TERR_1:port");
+ CHECK_LOG_CTX("Invalid bits - derived type adds new item \"test\".", "Path \"/TERR_1:port\".");
/* different max value => autoadd index */
schema = MODULE_CREATE_YANG("TERR_2", "leaf port {type bits {"
" bit first {position -1;} bit second;"
"}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_2\" failed.", NULL,
- "Invalid value \"-1\" of \"position\".", "Line number 5.");
+ CHECK_LOG_CTX("Parsing module \"TERR_2\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid value \"-1\" of \"position\".", "Line number 5.");
/* different max value => autoadd index */
schema = MODULE_CREATE_YANG("TERR_3", "leaf port {type bits {"
@@ -203,48 +203,48 @@ test_schema_yang(void **state)
"}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
CHECK_LOG_CTX("Invalid bits - it is not possible to auto-assign bit position for \"second\" since the highest value is already 4294967295.",
- "/TERR_3:port");
+ "Path \"/TERR_3:port\".");
schema = MODULE_CREATE_YANG("TERR_4", "leaf port {type bits {"
" bit first {position 10;} bit \"\";"
"}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_4\" failed.", NULL,
- "Statement argument is required.", "Line number 5.");
+ CHECK_LOG_CTX("Parsing module \"TERR_4\" failed.", NULL);
+ CHECK_LOG_CTX("Statement argument is required.", "Line number 5.");
/* wrong character */
schema = MODULE_CREATE_YANG("TERR_5", "leaf port {type bits {"
" bit first {position 10;} bit abcd^;"
"}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_5\" failed.", NULL,
- "Invalid identifier character '^' (0x005e).", "Line number 5.");
+ CHECK_LOG_CTX("Parsing module \"TERR_5\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid identifier character '^' (0x005e).", "Line number 5.");
schema = MODULE_CREATE_YANG("TERR_6", "leaf port {type bits {"
" bit hi; bit hi;"
"}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_6\" failed.", NULL,
- "Duplicate identifier \"hi\" of bit statement.", "Line number 5.");
+ CHECK_LOG_CTX("Parsing module \"TERR_6\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"hi\" of bit statement.", "Line number 5.");
/* wrong character */
schema = MODULE_CREATE_YANG("TERR_7", "leaf port {type bits {"
" bit first {position 10;} bit \"ab&cd\";"
"}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_7\" failed.", NULL,
- "Invalid identifier character '&' (0x0026).", "Line number 5.");
+ CHECK_LOG_CTX("Parsing module \"TERR_7\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid identifier character '&' (0x0026).", "Line number 5.");
schema = MODULE_CREATE_YANG("TERR_8", "leaf port {type bits {"
" bit first {position 10;} bit \"4abcd\";"
"}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_8\" failed.", NULL,
- "Invalid identifier first character '4' (0x0034).", "Line number 5.");
+ CHECK_LOG_CTX("Parsing module \"TERR_8\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid identifier first character '4' (0x0034).", "Line number 5.");
schema = MODULE_CREATE_YANG("TERR_9", "leaf port {type bits;}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Missing bit substatement for bits type.", "/TERR_9:port");
+ CHECK_LOG_CTX("Missing bit substatement for bits type.", "Path \"/TERR_9:port\".");
/* new features of YANG 1.1 in YANG 1.0 */
schema = "module TERR_10 {"
@@ -256,8 +256,8 @@ test_schema_yang(void **state)
" }}"
"}";
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_10\" failed.", NULL,
- "Invalid keyword \"if-feature\" as a child of \"bit\" - the statement is allowed only in YANG 1.1 modules.",
+ CHECK_LOG_CTX("Parsing module \"TERR_10\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid keyword \"if-feature\" as a child of \"bit\" - the statement is allowed only in YANG 1.1 modules.",
"Line number 1.");
schema = "module TERR_11 {"
@@ -267,7 +267,7 @@ test_schema_yang(void **state)
" leaf l {type mytype {bit one;}}"
"}";
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Bits type can be subtyped only in YANG 1.1 modules.", "/TERR_11:l");
+ CHECK_LOG_CTX("Bits type can be subtyped only in YANG 1.1 modules.", "Path \"/TERR_11:l\".");
/* feature is not present */
schema = MODULE_CREATE_YANG("IF_0", "feature f;"
@@ -415,7 +415,7 @@ test_schema_yin(void **state)
" <bit name=\"ten\"> <position value=\"11\"/> </bit> <bit name=\"two\"/>"
"</type></leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
- CHECK_LOG_CTX("Invalid bits - position of the item \"ten\" has changed from 10 to 11 in the derived type.", "/TERR_0:port");
+ CHECK_LOG_CTX("Invalid bits - position of the item \"ten\" has changed from 10 to 11 in the derived type.", "Path \"/TERR_0:port\".");
/* add new bit */
schema = MODULE_CREATE_YIN("TERR_1",
@@ -431,7 +431,7 @@ test_schema_yin(void **state)
" <bit name=\"test\"/>"
"</type></leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
- CHECK_LOG_CTX("Invalid bits - derived type adds new item \"test\".", "/TERR_1:port");
+ CHECK_LOG_CTX("Invalid bits - derived type adds new item \"test\".", "Path \"/TERR_1:port\".");
/* different max value => autoadd index */
schema = MODULE_CREATE_YIN("TERR_2",
@@ -440,8 +440,8 @@ test_schema_yin(void **state)
" <bit name=\"second\">"
"</type></leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_2\" failed.", NULL,
- "Invalid value \"-1\" of \"value\" attribute in \"position\" element.", "Line number 8.");
+ CHECK_LOG_CTX("Parsing module \"TERR_2\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid value \"-1\" of \"value\" attribute in \"position\" element.", "Line number 8.");
/* different max value => autoadd index */
schema = MODULE_CREATE_YIN("TERR_3",
@@ -451,7 +451,7 @@ test_schema_yin(void **state)
"</type></leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
CHECK_LOG_CTX("Invalid bits - it is not possible to auto-assign bit position for \"second\" since the highest value is already 4294967295.",
- "/TERR_3:port");
+ "Path \"/TERR_3:port\".");
schema = MODULE_CREATE_YIN("TERR_4",
"<leaf name=\"port\"> <type name=\"bits\">"
@@ -459,9 +459,8 @@ test_schema_yin(void **state)
" <bit name=\"second\"/>"
"</type></leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_4\" failed.", NULL,
- "Invalid identifier first character ' ' (0x0020).",
- "Line number 8.");
+ CHECK_LOG_CTX("Parsing module \"TERR_4\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid identifier first character ' ' (0x0020).", "Line number 8.");
schema = MODULE_CREATE_YIN("TERR_5",
"<leaf name=\"port\"> <type name=\"bits\">"
@@ -469,9 +468,8 @@ test_schema_yin(void **state)
" <bit name=\"second\"/>"
"</type></leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_5\" failed.", NULL,
- "Invalid identifier character ' ' (0x0020).",
- "Line number 8.");
+ CHECK_LOG_CTX("Parsing module \"TERR_5\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid identifier character ' ' (0x0020).", "Line number 8.");
schema = MODULE_CREATE_YIN("TERR_6",
"<leaf name=\"port\"> <type name=\"bits\">"
@@ -479,9 +477,8 @@ test_schema_yin(void **state)
" <bit name=\"hi\"/>"
"</type></leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_6\" failed.", NULL,
- "Duplicate identifier \"hi\" of bit statement.",
- "Line number 8.");
+ CHECK_LOG_CTX("Parsing module \"TERR_6\" failed.", NULL);
+ CHECK_LOG_CTX("Duplicate identifier \"hi\" of bit statement.", "Line number 8.");
schema = MODULE_CREATE_YIN("TERR_7",
"<leaf name=\"port\"> <type name=\"bits\">"
@@ -489,9 +486,8 @@ test_schema_yin(void **state)
" <bit name=\"second\"/>"
"</type></leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_7\" failed.", NULL,
- "Invalid identifier first character '4' (0x0034).",
- "Line number 8.");
+ CHECK_LOG_CTX("Parsing module \"TERR_7\" failed.", NULL);
+ CHECK_LOG_CTX("Invalid identifier first character '4' (0x0034).", "Line number 8.");
/* TEST EMPTY NAME*/
schema = MODULE_CREATE_YIN("TERR_8",
@@ -500,9 +496,8 @@ test_schema_yin(void **state)
" <bit name=\"second\"/>"
"</type></leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
- CHECK_LOG_CTX("Parsing module \"TERR_8\" failed.", NULL,
- "Empty identifier is not allowed.",
- "Line number 8.");
+ CHECK_LOG_CTX("Parsing module \"TERR_8\" failed.", NULL);
+ CHECK_LOG_CTX("Empty identifier is not allowed.", "Line number 8.");
}
static void
@@ -954,30 +949,6 @@ test_plugin_compare(void **state)
assert_int_equal(LY_ENOT, type->compare(&diff_type_val, &(values[1])));
type->free(UTEST_LYCTX, &(diff_type_val));
- /*
- * derivated type add some limitations
- */
- diff_type_text = val_init[2];
- diff_type = ((struct lysc_node_leaf *)mod->compiled->data->next->next)->type;
- ly_ret = diff_type->plugin->store(UTEST_LYCTX, diff_type, diff_type_text, strlen(diff_type_text),
- 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &diff_type_val, NULL, &err);
- assert_int_equal(LY_SUCCESS, ly_ret);
- assert_int_equal(LY_ENOT, type->compare(&diff_type_val, &(values[2])));
- assert_int_equal(LY_ENOT, type->compare(&diff_type_val, &(values[1])));
- type->free(UTEST_LYCTX, &(diff_type_val));
-
- /*
- * different type (STRING)
- */
- diff_type_text = val_init[2];
- diff_type = ((struct lysc_node_leaf *)mod->compiled->data->next->next->next)->type;
- ly_ret = diff_type->plugin->store(UTEST_LYCTX, diff_type, diff_type_text, strlen(diff_type_text),
- 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &diff_type_val, NULL, &err);
- assert_int_equal(LY_SUCCESS, ly_ret);
- assert_int_equal(LY_ENOT, type->compare(&diff_type_val, &(values[2])));
- assert_int_equal(LY_ENOT, type->compare(&diff_type_val, &(values[0])));
- type->free(UTEST_LYCTX, &(diff_type_val));
-
/* delete values */
for (unsigned int it = 0; it < sizeof(val_init) / sizeof(val_init[0]); it++) {
type->free(UTEST_LYCTX, &(values[it]));
diff --git a/tests/utests/types/identityref.c b/tests/utests/types/identityref.c
index cdfe057..107164d 100644
--- a/tests/utests/types/identityref.c
+++ b/tests/utests/types/identityref.c
@@ -27,15 +27,6 @@
NODES \
"}\n"
-#define TEST_SUCCESS_XML(MOD_NAME, NAMESPACES, NODE_NAME, DATA, TYPE, ...) \
- { \
- struct lyd_node *tree; \
- const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\" " NAMESPACES ">" DATA "</" NODE_NAME ">"; \
- CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \
- CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \
- lyd_free_all(tree); \
- }
-
#define TEST_ERROR_XML(MOD_NAME, NAMESPACES, NODE_NAME, DATA) \
{\
struct lyd_node *tree; \
@@ -64,21 +55,44 @@ static void
test_data_xml(void **state)
{
const char *schema, *schema2;
+ struct lyd_node *tree;
+ const char *data;
/* xml test */
- schema = MODULE_CREATE_YANG("ident-base", "identity ident-base;"
- "identity ident-imp {base ident-base;}");
+ schema = "module ident-base {"
+ " yang-version 1.1;"
+ " namespace \"urn:tests:ident-base\";"
+ " prefix ib;"
+ " identity ident-base;"
+ " identity ident-imp {base ident-base;}"
+ "}";
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
- schema2 = MODULE_CREATE_YANG("defs", "import ident-base {prefix ib;}"
- "identity ident1 {base ib:ident-base;}"
- "leaf l1 {type identityref {base ib:ident-base;}}");
+ schema2 = "module defs {"
+ " yang-version 1.1;"
+ " namespace \"urn:tests:defs\";"
+ " prefix d;"
+ " import ident-base {prefix ib;}"
+ " identity ident1 {base ib:ident-base;}"
+ " leaf l1 {type identityref {base ib:ident-base;}}"
+ "}";
UTEST_ADD_MODULE(schema2, LYS_IN_YANG, NULL, NULL);
- TEST_SUCCESS_XML("defs", "", "l1", "ident1", IDENT, "defs:ident1", "ident1");
-
- TEST_SUCCESS_XML("defs", "xmlns:i=\"urn:tests:ident-base\"", "l1", "i:ident-imp", IDENT, "ident-base:ident-imp",
- "ident-imp");
+ /* local ident, XML/JSON print */
+ data = "<l1 xmlns=\"urn:tests:defs\">ident1</l1>";
+ CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
+ CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, IDENT, "defs:ident1", "ident1");
+ CHECK_LYD_STRING_PARAM(tree, data, LYD_XML, LYD_PRINT_SHRINK);
+ CHECK_LYD_STRING_PARAM(tree, "{\"defs:l1\":\"ident1\"}", LYD_JSON, LYD_PRINT_SHRINK);
+ lyd_free_all(tree);
+
+ /* foreign ident, XML/JSON print */
+ data = "<l1 xmlns=\"urn:tests:defs\" xmlns:ib=\"urn:tests:ident-base\">ib:ident-imp</l1>";
+ CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
+ CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, IDENT, "ident-base:ident-imp", "ident-imp");
+ CHECK_LYD_STRING_PARAM(tree, data, LYD_XML, LYD_PRINT_SHRINK);
+ CHECK_LYD_STRING_PARAM(tree, "{\"defs:l1\":\"ident-base:ident-imp\"}", LYD_JSON, LYD_PRINT_SHRINK);
+ lyd_free_all(tree);
/* invalid value */
TEST_ERROR_XML("defs", "", "l1", "fast-ethernet");
diff --git a/tests/utests/types/instanceid.c b/tests/utests/types/instanceid.c
index 06c8622..3126f61 100644
--- a/tests/utests/types/instanceid.c
+++ b/tests/utests/types/instanceid.c
@@ -79,12 +79,12 @@ static void
test_data_xml(void **state)
{
const char *schema, *schema2;
- const enum ly_path_pred_type val1[] = {LY_PATH_PREDTYPE_NONE, LY_PATH_PREDTYPE_NONE};
- const enum ly_path_pred_type val2[] = {LY_PATH_PREDTYPE_LIST, LY_PATH_PREDTYPE_NONE};
+ const enum ly_path_pred_type val1[] = {0, 0};
+ const enum ly_path_pred_type val2[] = {LY_PATH_PREDTYPE_LIST, 0};
const enum ly_path_pred_type val3[] = {LY_PATH_PREDTYPE_LEAFLIST};
- const enum ly_path_pred_type val4[] = {LY_PATH_PREDTYPE_LIST, LY_PATH_PREDTYPE_NONE};
- const enum ly_path_pred_type val5[] = {LY_PATH_PREDTYPE_LIST, LY_PATH_PREDTYPE_NONE};
- const enum ly_path_pred_type val6[] = {LY_PATH_PREDTYPE_LIST, LY_PATH_PREDTYPE_NONE};
+ const enum ly_path_pred_type val4[] = {LY_PATH_PREDTYPE_LIST, 0};
+ const enum ly_path_pred_type val5[] = {LY_PATH_PREDTYPE_LIST, 0};
+ const enum ly_path_pred_type val6[] = {LY_PATH_PREDTYPE_LIST, 0};
/* xml test */
schema = MODULE_CREATE_YANG("mod", "container cont {leaf l2 {type empty;}}");
@@ -136,22 +136,23 @@ test_data_xml(void **state)
TEST_ERROR_XML2("<list xmlns=\"urn:tests:defs\"><id>a</id></list>"
"<list xmlns=\"urn:tests:defs\"><id>b</id><value>x</value></list>",
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l1", "/xdf:list[2]/xdf:value", LY_EVALID);
- CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list[2]/xdf:value\" value - semantic error.",
+ CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list[2]/xdf:value\" value - semantic error: "
+ "Positional predicate defined for configuration list \"list\" in path.",
"Schema location \"/defs:l1\", line number 1.");
TEST_ERROR_XML2("",
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l1", "/t:cont/t:1l", LY_EVALID);
- CHECK_LOG_CTX("Invalid instance-identifier \"/t:cont/t:1l\" value - syntax error.",
+ CHECK_LOG_CTX("Invalid instance-identifier \"/t:cont/t:1l\" value - syntax error: Invalid character 't'[9] of expression '/t:cont/t:1l'.",
"Schema location \"/defs:l1\", line number 1.");
TEST_ERROR_XML2("",
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l1", "/t:cont:t:1l", LY_EVALID);
- CHECK_LOG_CTX("Invalid instance-identifier \"/t:cont:t:1l\" value - syntax error.",
+ CHECK_LOG_CTX("Invalid instance-identifier \"/t:cont:t:1l\" value - syntax error: Invalid character ':'[8] of expression '/t:cont:t:1l'.",
"Schema location \"/defs:l1\", line number 1.");
TEST_ERROR_XML2("",
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l1", "/xdf:cont/xdf:invalid/xdf:path", LY_EVALID);
- CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:cont/xdf:invalid/xdf:path\" value - semantic error.",
+ CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:cont/xdf:invalid/xdf:path\" value - semantic error: Not found node \"invalid\" in path.",
"Schema location \"/defs:l1\", line number 1.");
/* non-existing instances, instance-identifier is here in JSON format because it is already in internal
@@ -190,72 +191,72 @@ test_data_xml(void **state)
/* more errors */
TEST_ERROR_XML2("<llist xmlns=\"urn:tests:defs\">x</llist>",
"defs", "xmlns:t=\"urn:tests:defs\"", "t:l1", "/t:llist[1", LY_EVALID);
- CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[1\" value - syntax error.",
+ CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[1\" value - syntax error: Unexpected XPath expression end.",
"Schema location \"/defs:l1\", line number 1.");
TEST_ERROR_XML2("<cont xmlns=\"urn:tests:mod\"/>",
"defs", "xmlns:m=\"urn:tests:mod\"", "l1", "/m:cont[1]", LY_EVALID);
- CHECK_LOG_CTX("Invalid instance-identifier \"/m:cont[1]\" value - semantic error.",
+ CHECK_LOG_CTX("Invalid instance-identifier \"/m:cont[1]\" value - semantic error: Positional predicate defined for container \"cont\" in path.",
"Schema location \"/defs:l1\", line number 1.");
TEST_ERROR_XML2("<cont xmlns=\"urn:tests:mod\"/>",
"defs", "xmlns:m=\"urn:tests:mod\"", "l1", "[1]", LY_EVALID);
- CHECK_LOG_CTX("Invalid instance-identifier \"[1]\" value - syntax error.",
+ CHECK_LOG_CTX("Invalid instance-identifier \"[1]\" value - syntax error: Unexpected XPath token \"[\" (\"[1]\"), expected \"Operator(Path)\".",
"Schema location \"/defs:l1\", line number 1.");
TEST_ERROR_XML2("<cont xmlns=\"urn:tests:mod\"><l2/></cont>",
"defs", "xmlns:m=\"urn:tests:mod\"", "l1", "/m:cont/m:l2[l2='1']", LY_EVALID);
- CHECK_LOG_CTX("Invalid instance-identifier \"/m:cont/m:l2[l2='1']\" value - syntax error.",
+ CHECK_LOG_CTX("Invalid instance-identifier \"/m:cont/m:l2[l2='1']\" value - syntax error: Prefix missing for \"l2\" in path.",
"Schema location \"/defs:l1\", line number 1.");
TEST_ERROR_XML2("<cont xmlns=\"urn:tests:mod\"><l2/></cont>",
"defs", "xmlns:m=\"urn:tests:mod\"", "l1", "/m:cont/m:l2[m:l2='1']", LY_EVALID);
- CHECK_LOG_CTX("Invalid instance-identifier \"/m:cont/m:l2[m:l2='1']\" value - semantic error.",
+ CHECK_LOG_CTX("Invalid instance-identifier \"/m:cont/m:l2[m:l2='1']\" value - semantic error: List predicate defined for leaf \"l2\" in path.",
"Schema location \"/defs:l1\", line number 1.");
TEST_ERROR_XML2("<llist xmlns=\"urn:tests:defs\">1</llist><llist xmlns=\"urn:tests:defs\">2</llist>",
"defs", "xmlns:t=\"urn:tests:defs\"", "t:l1", "/t:llist[4]", LY_EVALID);
- CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[4]\" value - semantic error.",
+ CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[4]\" value - semantic error: Positional predicate defined for configuration leaf-list \"llist\" in path.",
"Schema location \"/defs:l1\", line number 1.");
TEST_ERROR_XML2("",
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/t:llist[6]", LY_EVALID);
- CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[6]\" value - semantic error.",
+ CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[6]\" value - semantic error: No module connected with the prefix \"t\" found (prefix format XML prefixes).",
"Schema location \"/defs:l2\", line number 1.");
TEST_ERROR_XML2("<list xmlns=\"urn:tests:defs\"><id>1</id><value>x</value></list>",
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/xdf:list[xdf:value='x']", LY_EVALID);
- CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list[xdf:value='x']\" value - semantic error.",
+ CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list[xdf:value='x']\" value - semantic error: Key expected instead of leaf \"value\" in path.",
"Schema location \"/defs:l2\", line number 1.");
TEST_ERROR_XML2("",
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/xdf:list[.='x']", LY_EVALID);
- CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list[.='x']\" value - semantic error.",
+ CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list[.='x']\" value - semantic error: Leaf-list predicate defined for list \"list\" in path.",
"Schema location \"/defs:l2\", line number 1.");
TEST_ERROR_XML2("<llist xmlns=\"urn:tests:defs\">1</llist>",
"defs", "xmlns:t=\"urn:tests:defs\"", "t:l1", "/t:llist[.='x']", LY_EVALID);
- CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[.='x']\" value - semantic error.",
+ CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[.='x']\" value - semantic error: Invalid type uint32 value \"x\".",
"Schema location \"/defs:l1\", line number 1.");
TEST_ERROR_XML2("",
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/t:llist[1][2]", LY_EVALID);
- CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[1][2]\" value - syntax error.",
+ CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[1][2]\" value - syntax error: Unparsed characters \"[2]\" left at the end of path.",
"Schema location \"/defs:l2\", line number 1.");
TEST_ERROR_XML2("",
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/t:llist[.='a'][.='b']", LY_EVALID);
- CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[.='a'][.='b']\" value - syntax error.",
+ CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[.='a'][.='b']\" value - syntax error: Unparsed characters \"[.='b']\" left at the end of path.",
"Schema location \"/defs:l2\", line number 1.");
TEST_ERROR_XML2("<list xmlns=\"urn:tests:defs\"><id>1</id><value>x</value></list>",
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/xdf:list[xdf:id='1'][xdf:id='2']/xdf:value", LY_EVALID);
- CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list[xdf:id='1'][xdf:id='2']/xdf:value\" value - syntax error.",
+ CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list[xdf:id='1'][xdf:id='2']/xdf:value\" value - syntax error: Duplicate predicate key \"id\" in path.",
"Schema location \"/defs:l2\", line number 1.");
TEST_ERROR_XML2("",
"defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/xdf:list2[xdf:id='1']/xdf:value", LY_EVALID);
- CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list2[xdf:id='1']/xdf:value\" value - semantic error.",
+ CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list2[xdf:id='1']/xdf:value\" value - semantic error: Predicate missing for a key of list \"list2\" in path.",
"Schema location \"/defs:l2\", line number 1.");
}
diff --git a/tests/utests/types/int8.c b/tests/utests/types/int8.c
index 7d0b9ad..198d1f7 100644
--- a/tests/utests/types/int8.c
+++ b/tests/utests/types/int8.c
@@ -240,22 +240,22 @@ test_schema_yang(void **state)
/* TEST ERROR -60 .. 0 | 0 .. 127 */
schema = MODULE_CREATE_YANG("ERR0", "leaf port {type int8 {range \"-60 .. 0 | 0 .. 127\";}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EEXIST);
- CHECK_LOG_CTX("Invalid range restriction - values are not in ascending order (0).", "/ERR0:port");
+ CHECK_LOG_CTX("Invalid range restriction - values are not in ascending order (0).", "Path \"/ERR0:port\".");
/* TEST ERROR 0 .. 128 */
schema = MODULE_CREATE_YANG("ERR1", "leaf port {type int8 {range \"0 .. 128\";}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EDENIED);
- CHECK_LOG_CTX("Invalid range restriction - value \"128\" does not fit the type limitations.", "/ERR1:port");
+ CHECK_LOG_CTX("Invalid range restriction - value \"128\" does not fit the type limitations.", "Path \"/ERR1:port\".");
/* TEST ERROR -129 .. 126 */
schema = MODULE_CREATE_YANG("ERR2", "leaf port {type int8 {range \"-129 .. 0\";}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EDENIED);
- CHECK_LOG_CTX("Invalid range restriction - value \"-129\" does not fit the type limitations.", "/ERR2:port");
+ CHECK_LOG_CTX("Invalid range restriction - value \"-129\" does not fit the type limitations.", "Path \"/ERR2:port\".");
/* TEST ERROR 0 */
schema = MODULE_CREATE_YANG("ERR3", "leaf port {type int8 {range \"-129\";}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EDENIED);
- CHECK_LOG_CTX("Invalid range restriction - value \"-129\" does not fit the type limitations.", "/ERR3:port");
+ CHECK_LOG_CTX("Invalid range restriction - value \"-129\" does not fit the type limitations.", "Path \"/ERR3:port\".");
/*
* TEST MODULE SUBTYPE
@@ -374,7 +374,7 @@ test_schema_yang(void **state)
"leaf my_leaf {type my_int_type {range \"min .. max\";}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
CHECK_LOG_CTX("Invalid range restriction - the derived restriction (min .. max) is not equally or more limiting.",
- "/TS_ERR0:my_leaf");
+ "Path \"/TS_ERR0:my_leaf\".");
/* TEST SUBTYPE ERROR -80 .. 80 */
schema = MODULE_CREATE_YANG("TS_ERR1",
@@ -382,7 +382,7 @@ test_schema_yang(void **state)
" leaf my_leaf {type my_int_type {range \"-80 .. 80\";}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
CHECK_LOG_CTX("Invalid range restriction - the derived restriction (-80 .. 80) is not equally or more limiting.",
- "/TS_ERR1:my_leaf");
+ "Path \"/TS_ERR1:my_leaf\".");
/* TEST SUBTYPE ERROR 0 .. max */
schema = MODULE_CREATE_YANG("TS_ERR2",
@@ -390,7 +390,7 @@ test_schema_yang(void **state)
"leaf my_leaf {type my_int_type {range \"0 .. max\";}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
CHECK_LOG_CTX("Invalid range restriction - the derived restriction (0 .. max) is not equally or more limiting.",
- "/TS_ERR2:my_leaf");
+ "Path \"/TS_ERR2:my_leaf\".");
/* TEST SUBTYPE ERROR -2 .. 2 */
schema = MODULE_CREATE_YANG("TS_ERR3",
@@ -398,7 +398,7 @@ test_schema_yang(void **state)
"leaf my_leaf {type my_int_type {range \"-2 .. 2\";}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
CHECK_LOG_CTX("Invalid range restriction - the derived restriction (-2 .. 2) is not equally or more limiting.",
- "/TS_ERR3:my_leaf");
+ "Path \"/TS_ERR3:my_leaf\".");
/* TEST SUBTYPE ERROR -2 .. 2 */
schema = MODULE_CREATE_YANG("TS_ERR4",
@@ -406,7 +406,7 @@ test_schema_yang(void **state)
"leaf my_leaf {type my_int_type {range \"-100 .. -90 | 100 .. 128\";}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EDENIED);
CHECK_LOG_CTX("Invalid range restriction - value \"128\" does not fit the type limitations.",
- "/TS_ERR4:my_leaf");
+ "Path \"/TS_ERR4:my_leaf\".");
/*
* TEST DEFAULT VALUE
@@ -745,7 +745,7 @@ test_schema_yin(void **state)
" <type name=\"int8\"> <range value = \"min .. 0 | 0 .. 12\"/> </type>"
"</leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EEXIST);
- CHECK_LOG_CTX("Invalid range restriction - values are not in ascending order (0).", "/TE0:port");
+ CHECK_LOG_CTX("Invalid range restriction - values are not in ascending order (0).", "Path \"/TE0:port\".");
/* TEST ERROR 0 .. 128 */
schema = MODULE_CREATE_YIN("TE1",
@@ -753,7 +753,7 @@ test_schema_yin(void **state)
" <type name=\"int8\"> <range value = \"0 .. 128\"/> </type>"
"</leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EDENIED);
- CHECK_LOG_CTX("Invalid range restriction - value \"128\" does not fit the type limitations.", "/TE1:port");
+ CHECK_LOG_CTX("Invalid range restriction - value \"128\" does not fit the type limitations.", "Path \"/TE1:port\".");
/* TEST ERROR -129 .. 126 */
schema = MODULE_CREATE_YIN("TE2",
@@ -761,7 +761,7 @@ test_schema_yin(void **state)
" <type name=\"int8\"> <range value =\"-129 .. 126\"/> </type>"
"</leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EDENIED);
- CHECK_LOG_CTX("Invalid range restriction - value \"-129\" does not fit the type limitations.", "/TE2:port");
+ CHECK_LOG_CTX("Invalid range restriction - value \"-129\" does not fit the type limitations.", "Path \"/TE2:port\".");
/* TEST YIN */
schema = MODULE_CREATE_YIN("TS0",
@@ -817,7 +817,7 @@ test_schema_yin(void **state)
"</leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
CHECK_LOG_CTX("Invalid range restriction - the derived restriction (min .. max) is not equally or more limiting.",
- "/TS_ERR1:port");
+ "Path \"/TS_ERR1:port\".");
/* TEST ERROR */
schema = MODULE_CREATE_YIN("TS_ERR2",
@@ -829,7 +829,7 @@ test_schema_yin(void **state)
"</leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
CHECK_LOG_CTX("Invalid range restriction - the derived restriction (5 .. 11) is not equally or more limiting.",
- "/TS_ERR2:port");
+ "Path \"/TS_ERR2:port\".");
/* TEST DEFAULT VALUE */
schema = MODULE_CREATE_YIN("DF0",
@@ -1243,8 +1243,14 @@ test_data_json(void **state)
TEST_SUCCESS_JSON("T0", "127", INT8, "127", 127);
/* leading zeros */
TEST_ERROR_JSON("T0", "015");
+ CHECK_LOG_CTX("Invalid character sequence \"15}\", expected a JSON object-end or next item.",
+ "Line number 1.");
TEST_ERROR_JSON("T0", "-015");
+ CHECK_LOG_CTX("Invalid character sequence \"15}\", expected a JSON object-end or next item.",
+ "Line number 1.");
TEST_ERROR_JSON("defs", "+50");
+ CHECK_LOG_CTX("Invalid character sequence \"+50}\", expected a JSON value.",
+ "Line number 1.");
TEST_ERROR_JSON("T0", "-129");
CHECK_LOG_CTX("Value \"-129\" is out of type int8 min/max bounds.",
"Schema location \"/T0:port\", line number 1.");
@@ -1510,6 +1516,7 @@ test_plugin_store(void **state)
ly_ret = type->store(UTEST_LYCTX, &lysc_type_test, val_text, strlen(val_text),
0, LY_VALUE_XML, NULL, LYD_VALHINT_HEXNUM, NULL, &value, NULL, &err);
assert_int_equal(LY_EINT, ly_ret);
+ UTEST_LOG_CTX_CLEAN;
/*
* ERROR TESTS
@@ -1541,6 +1548,8 @@ test_plugin_store(void **state)
0, LY_VALUE_XML, NULL, LYD_VALHINT_DECNUM, NULL, &value, NULL, &err);
assert_int_equal(LY_EVALID, ly_ret);
ly_err_free(err);
+
+ UTEST_LOG_CTX_CLEAN;
}
static void
diff --git a/tests/utests/types/leafref.c b/tests/utests/types/leafref.c
index c8d0cb6..21e91cd 100644
--- a/tests/utests/types/leafref.c
+++ b/tests/utests/types/leafref.c
@@ -209,6 +209,70 @@ test_plugin_lyb(void **state)
TEST_SUCCESS_LYB("lyb", "lst", "key_str", "lref", "key_str");
}
+static void
+test_data_xpath_json(void **state)
+{
+ const char *schema, *data;
+ struct lyd_node *tree;
+
+ ly_ctx_set_options(UTEST_LYCTX, LY_CTX_LEAFREF_EXTENDED);
+
+ /* json xpath test */
+ schema = MODULE_CREATE_YANG("xp_test",
+ "list l1 {key t1;"
+ "leaf t1 {type uint8;}"
+ "list l2 {key t2;"
+ "leaf t2 {type uint8;}"
+ "leaf-list l3 {type uint8;}"
+ "}}"
+ "leaf r1 {type leafref {path \"../l1/t1\";}}"
+ "leaf r2 {type leafref {path \"deref(../r1)/../l2/t2\";}}"
+ "leaf r3 {type leafref {path \"deref(../r2)/../l3\";}}");
+
+ UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
+
+ data = "{"
+ " \"xp_test:l1\":[{\"t1\": 1,\"l2\":[{\"t2\": 2,\"l3\":[3]}]}],"
+ " \"xp_test:r1\": 1,"
+ " \"xp_test:r2\": 2,"
+ " \"xp_test:r3\": 3"
+ "}";
+ CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
+ lyd_free_all(tree);
+}
+
+static void
+test_xpath_invalid_schema(void **state)
+{
+ const char *schema1, *schema2;
+
+ ly_ctx_set_options(UTEST_LYCTX, LY_CTX_LEAFREF_EXTENDED);
+ schema1 = MODULE_CREATE_YANG("xp_test",
+ "list l1 {key t1;"
+ "leaf t1 {type uint8;}"
+ "list l2 {key t2;"
+ "leaf t2 {type uint8;}"
+ "leaf-list l3 {type uint8;}"
+ "}}"
+ "leaf r1 {type leafref {path \"deref(../l1)/../l2/t2\";}}");
+
+ UTEST_INVALID_MODULE(schema1, LYS_IN_YANG, NULL, LY_EVALID)
+ CHECK_LOG_CTX("The deref function target node \"l1\" is not leaf nor leaflist", "Schema location \"/xp_test:r1\".");
+
+ schema2 = MODULE_CREATE_YANG("xp_test",
+ "list l1 {key t1;"
+ "leaf t1 {type uint8;}"
+ "list l2 {key t2;"
+ "leaf t2 {type uint8;}"
+ "leaf-list l3 {type uint8;}"
+ "}}"
+ "leaf r1 {type uint8;}"
+ "leaf r2 {type leafref {path \"deref(../r1)/../l2/t2\";}}");
+
+ UTEST_INVALID_MODULE(schema2, LYS_IN_YANG, NULL, LY_EVALID)
+ CHECK_LOG_CTX("The deref function target node \"r1\" is not leafref", "Schema location \"/xp_test:r2\".");
+}
+
int
main(void)
{
@@ -216,6 +280,8 @@ main(void)
UTEST(test_data_xml),
UTEST(test_data_json),
UTEST(test_plugin_lyb),
+ UTEST(test_data_xpath_json),
+ UTEST(test_xpath_invalid_schema)
};
return cmocka_run_group_tests(tests, NULL, NULL);
diff --git a/tests/utests/types/string.c b/tests/utests/types/string.c
index d232e9d..ce5ae8d 100644
--- a/tests/utests/types/string.c
+++ b/tests/utests/types/string.c
@@ -200,15 +200,15 @@ test_schema_yang(void **state)
/* ERROR TESTS NEGATIVE VALUE */
schema = MODULE_CREATE_YANG("ERR0", "leaf port {type string {length \"-1 .. 20\";}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EDENIED);
- CHECK_LOG_CTX("Invalid length restriction - value \"-1\" does not fit the type limitations.", "/ERR0:port");
+ CHECK_LOG_CTX("Invalid length restriction - value \"-1\" does not fit the type limitations.", "Path \"/ERR0:port\".");
schema = MODULE_CREATE_YANG("ERR1", "leaf port {type string {length \"100 .. 18446744073709551616\";}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
- CHECK_LOG_CTX("Invalid length restriction - invalid value \"18446744073709551616\".", "/ERR1:port");
+ CHECK_LOG_CTX("Invalid length restriction - invalid value \"18446744073709551616\".", "Path \"/ERR1:port\".");
schema = MODULE_CREATE_YANG("ERR2", "leaf port {type string {length \"10 .. 20 | 20 .. 30\";}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EEXIST);
- CHECK_LOG_CTX("Invalid length restriction - values are not in ascending order (20).", "/ERR2:port");
+ CHECK_LOG_CTX("Invalid length restriction - values are not in ascending order (20).", "Path \"/ERR2:port\".");
schema = MODULE_CREATE_YANG("ERR3",
"typedef my_type {"
@@ -216,7 +216,7 @@ test_schema_yang(void **state)
"}"
"leaf port {type my_type {length \"-1 .. 15\";}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EDENIED);
- CHECK_LOG_CTX("Invalid length restriction - value \"-1\" does not fit the type limitations.", "/ERR3:port");
+ CHECK_LOG_CTX("Invalid length restriction - value \"-1\" does not fit the type limitations.", "Path \"/ERR3:port\".");
/*
* PATTERN
@@ -286,7 +286,7 @@ test_schema_yang(void **state)
"}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
CHECK_LOG_CTX("Regular expression \"[a-zA-Z_[a-zA-Z0-9\\-_.*\" is not valid (\"\": missing terminating ] for character class).",
- "/TPATTERN_ERR_0:port");
+ "Path \"/TPATTERN_ERR_0:port\".");
schema = MODULE_CREATE_YANG("TDEFAULT_0",
"typedef my_type {"
@@ -323,14 +323,14 @@ test_schema_yang(void **state)
"}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
CHECK_LOG_CTX("Regular expression \"\\[a]b\" is not valid (\"]b\": character group doesn't begin with '[').",
- "/TPATTERN_BC_ERR_1:port");
+ "Path \"/TPATTERN_BC_ERR_1:port\".");
schema = MODULE_CREATE_YANG("TPATTERN_BC_ERR_2", "leaf port {type string {"
"pattern \"\\\\[a]b\";" /* pattern "\\[a]b"; */
"}}");
UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID);
CHECK_LOG_CTX("Regular expression \"\\[a]b\" is not valid (\"]b\": character group doesn't begin with '[').",
- "/TPATTERN_BC_ERR_2:port");
+ "Path \"/TPATTERN_BC_ERR_2:port\".");
/* PATTERN AND LENGTH */
schema = MODULE_CREATE_YANG("TPL_0",
@@ -467,26 +467,26 @@ test_schema_yin(void **state)
schema = MODULE_CREATE_YIN("ERR0", "<leaf name=\"port\"> <type name=\"string\">"
"<length value =\"-1 .. 20\"/> </type></leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EDENIED);
- CHECK_LOG_CTX("Invalid length restriction - value \"-1\" does not fit the type limitations.", "/ERR0:port");
+ CHECK_LOG_CTX("Invalid length restriction - value \"-1\" does not fit the type limitations.", "Path \"/ERR0:port\".");
schema = MODULE_CREATE_YIN("ERR1", "<leaf name=\"port\"> <type name=\"string\">"
"<length value=\"100 .. 18446744073709551616\"/>"
"</type> </leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
- CHECK_LOG_CTX("Invalid length restriction - invalid value \"18446744073709551616\".", "/ERR1:port");
+ CHECK_LOG_CTX("Invalid length restriction - invalid value \"18446744073709551616\".", "Path \"/ERR1:port\".");
schema = MODULE_CREATE_YIN("ERR2", "<leaf name=\"port\">"
"<type name=\"string\"> <length value=\"10 .. 20 | 20 .. 30\"/>"
"</type> </leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EEXIST);
- CHECK_LOG_CTX("Invalid length restriction - values are not in ascending order (20).", "/ERR2:port");
+ CHECK_LOG_CTX("Invalid length restriction - values are not in ascending order (20).", "Path \"/ERR2:port\".");
schema = MODULE_CREATE_YIN("ERR3",
"<typedef name=\"my_type\"> <type name=\"string\"/> </typedef>"
"<leaf name=\"port\"> <type name=\"my_type\"> <length value=\"-1 .. 15\"/>"
"</type> </leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EDENIED);
- CHECK_LOG_CTX("Invalid length restriction - value \"-1\" does not fit the type limitations.", "/ERR3:port");
+ CHECK_LOG_CTX("Invalid length restriction - value \"-1\" does not fit the type limitations.", "Path \"/ERR3:port\".");
/*
* PATTERN
@@ -557,7 +557,7 @@ test_schema_yin(void **state)
"</type> </leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
CHECK_LOG_CTX("Regular expression \"[a-zA-Z_][a-zA-Z0-9\\-_.*\" is not valid (\"\": missing terminating ] for character class).",
- "/TPATTERN_ERR_0:port");
+ "Path \"/TPATTERN_ERR_0:port\".");
/*
* DEFAUT VALUE
@@ -618,16 +618,8 @@ test_schema_yin(void **state)
"</typedef>"
"<leaf name=\"port\"> <type name=\"my_type\"/> </leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
-
- schema = MODULE_CREATE_YIN("TDEFAULT_2",
- "<typedef name=\"my_type\">"
- " <type name=\"string\">"
- " <length value=\"2\"/>"
- " </type>"
- " <default value=\"a1i-j&lt;\"/>"
- "</typedef>"
- "<leaf name=\"port\"> <type name=\"my_type\"/> </leaf>");
- UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
+ CHECK_LOG_CTX("Invalid default - value does not fit the type (Unsatisfied length - string \"a1i-j<\" length is not allowed.).",
+ "Schema location \"/TDEFAULT_2:port\".");
schema = MODULE_CREATE_YIN("TDEFAULT_3",
"<typedef name=\"my_type\">"
@@ -636,6 +628,8 @@ test_schema_yin(void **state)
"</type> </typedef>"
"<leaf name=\"port\"><type name=\"my_type\"> <pattern value=\"bcd.*\"/> </type></leaf>");
UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID);
+ CHECK_LOG_CTX("Invalid default - value does not fit the type (Unsatisfied pattern - \"a1i-j<\" does not conform to \"bcd.*\".).",
+ "Schema location \"/TDEFAULT_3:port\".");
}
@@ -874,7 +868,7 @@ test_data_json(void **state)
CHECK_LOG_CTX("Invalid character reference \"\\f\" (0x0000000c).", "Line number 1.");
TEST_ERROR_JSON("T0", "\"");
- CHECK_LOG_CTX("Unexpected character \"\"\" after JSON string.", "Line number 1.");
+ CHECK_LOG_CTX("Invalid character sequence \"\"}\", expected a JSON object-end or next item.", "Line number 1.");
TEST_ERROR_JSON("T0", "aabb \\x");
CHECK_LOG_CTX("Invalid character escape sequence \\x.", "Line number 1.");
@@ -1258,26 +1252,6 @@ test_plugin_compare(void **state)
assert_int_equal(LY_ENOT, type->compare(&diff_type_val, &(values[1])));
type->free(UTEST_LYCTX, &(diff_type_val));
- /* original type */
- diff_type_text = "hi";
- diff_type = ((struct lysc_node_leaf *) mod->compiled->data->next->next)->type;
- ly_ret = diff_type->plugin->store(UTEST_LYCTX, diff_type, diff_type_text, strlen(diff_type_text),
- 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &diff_type_val, NULL, &err);
- assert_int_equal(LY_SUCCESS, ly_ret);
- assert_int_equal(LY_ENOT, type->compare(&diff_type_val, &(values[0])));
- assert_int_equal(LY_ENOT, type->compare(&diff_type_val, &(values[1])));
- type->free(UTEST_LYCTX, &(diff_type_val));
-
- /* different type (UINT8) */
- diff_type_text = "20";
- diff_type = ((struct lysc_node_leaf *) mod->compiled->data->next->next->next)->type;
- ly_ret = diff_type->plugin->store(UTEST_LYCTX, diff_type, diff_type_text, strlen(diff_type_text),
- 0, LY_VALUE_XML, NULL, LYD_VALHINT_DECNUM, NULL, &diff_type_val, NULL, &err);
- assert_int_equal(LY_SUCCESS, ly_ret);
- assert_int_equal(LY_ENOT, type->compare(&diff_type_val, &(values[0])));
- assert_int_equal(LY_ENOT, type->compare(&diff_type_val, &(values[1])));
- type->free(UTEST_LYCTX, &(diff_type_val));
-
/* delete values */
for (int unsigned it = 0; it < sizeof(val_init) / sizeof(val_init[0]); it++) {
type->free(UTEST_LYCTX, &(values[it]));
diff --git a/tests/utests/types/union.c b/tests/utests/types/union.c
index 9a0705a..d23cbf1 100644
--- a/tests/utests/types/union.c
+++ b/tests/utests/types/union.c
@@ -104,11 +104,34 @@ test_data_xml(void **state)
/* invalid value */
TEST_ERROR_XML2("",
"defs", "", "un1", "123456789012345678901", LY_EVALID);
- CHECK_LOG_CTX("Invalid union value \"123456789012345678901\" - no matching subtype found.",
+ CHECK_LOG_CTX("Invalid union value \"123456789012345678901\" - no matching subtype found:\n"
+ " libyang 2 - leafref, version 1: Invalid type int8 value \"123456789012345678901\".\n"
+ " libyang 2 - leafref, version 1: Invalid type int64 value \"123456789012345678901\".\n"
+ " libyang 2 - identityref, version 1: Invalid identityref \"123456789012345678901\" value - identity not found in module \"defs\".\n"
+ " libyang 2 - instance-identifier, version 1: Invalid instance-identifier \"123456789012345678901\" value - syntax error.\n"
+ " libyang 2 - string, version 1: Unsatisfied length - string \"123456789012345678901\" length is not allowed.\n",
"Schema location \"/defs:un1\", line number 1.");
}
static void
+test_data_json(void **state)
+{
+ const char *schema, *data;
+ struct lyd_node *tree;
+
+ /* xml test */
+ schema = MODULE_CREATE_YANG("defs", "leaf un21 {type union {type uint8; type string;}}"
+ "leaf un22 {type union {type uint16; type string;}}"
+ "leaf un2 {type union {type leafref {path /un21; require-instance false;} type leafref {path /un22; require-instance false;}}}");
+ UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
+
+ data = "{\"defs:un2\":\"str\"}";
+ CHECK_PARSE_LYD_PARAM(data, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
+ CHECK_LYD_STRING_PARAM(tree, data, LYD_JSON, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS);
+ lyd_free_all(tree);
+}
+
+static void
test_plugin_lyb(void **state)
{
const char *schema;
@@ -124,12 +147,60 @@ test_plugin_lyb(void **state)
TEST_SUCCESS_LYB("lyb", "un1", "");
}
+static void
+test_validation(void **state)
+{
+ const char *schema, *data;
+ struct lyd_node *tree;
+ char *out;
+
+ schema = MODULE_CREATE_YANG("val",
+ "leaf l1 {\n"
+ " type union {\n"
+ " type uint32 {\n"
+ " range \"0..1048575\";\n"
+ " }\n"
+ " type enumeration {\n"
+ " enum auto;\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "leaf int8 {type int8 {range 10..20;}}\n"
+ "leaf l2 {\n"
+ " type union {\n"
+ " type leafref {path /int8; require-instance true;}\n"
+ " type string;\n"
+ " }\n"
+ "}\n");
+ UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
+
+ /* parse from LYB */
+ data = "<l1 xmlns=\"urn:tests:val\">auto</l1><int8 xmlns=\"urn:tests:val\">15</int8><l2 xmlns=\"urn:tests:val\">15</l2>";
+ CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
+ assert_int_equal(LY_SUCCESS, lyd_print_mem(&out, tree, LYD_LYB, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS));
+ lyd_free_all(tree);
+ CHECK_PARSE_LYD_PARAM(out, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
+ free(out);
+
+ /* validate */
+ assert_int_equal(LY_SUCCESS, lyd_validate_all(&tree, NULL, LYD_VALIDATE_PRESENT, NULL));
+
+ /* print and compare */
+ assert_int_equal(LY_SUCCESS, lyd_print_mem(&out, tree, LYD_XML, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS));
+ assert_string_equal(out, data);
+
+ free(out);
+ lyd_free_all(tree);
+}
+
int
main(void)
{
const struct CMUnitTest tests[] = {
UTEST(test_data_xml),
+ UTEST(test_data_json),
UTEST(test_plugin_lyb),
+ UTEST(test_validation),
};
return cmocka_run_group_tests(tests, NULL, NULL);
diff --git a/tests/utests/types/yang_types.c b/tests/utests/types/yang_types.c
index 6ce7671..0f78455 100644
--- a/tests/utests/types/yang_types.c
+++ b/tests/utests/types/yang_types.c
@@ -3,7 +3,7 @@
* @author Michal Vaško <mvasko@cesnet.cz>
* @brief test for ietf-yang-types values
*
- * Copyright (c) 2021 CESNET, z.s.p.o.
+ * Copyright (c) 2021 - 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.
@@ -52,11 +52,11 @@
lyd_free_all(tree); \
}
-#define TEST_ERROR_XML(MOD_NAME, NODE_NAME, DATA) \
+#define TEST_ERROR_XML(MOD_NAME, NODE_NAME, DATA, RET) \
{\
struct lyd_node *tree; \
const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \
- CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \
+ CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, RET, tree); \
assert_null(tree); \
}
@@ -84,14 +84,15 @@ test_data_xml(void **state)
/* xml test */
schema = MODULE_CREATE_YANG("a",
"leaf l {type yang:date-and-time;}"
- "leaf l2 {type yang:xpath1.0;}");
+ "leaf l21 {type yang:hex-string;}"
+ "leaf l22 {type yang:uuid;}"
+ "leaf l3 {type yang:xpath1.0;}");
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
schema = MODULE_CREATE_YANG("b",
"");
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
/* date-and-time */
-#if defined (HAVE_TM_GMTOFF) && defined (HAVE_TIME_H_TIMEZONE)
TEST_SUCCESS_XML("a", "l", "2005-05-25T23:15:15.88888Z", STRING, "2005-05-25T21:15:15.88888-02:00");
TEST_SUCCESS_XML("a", "l", "2005-05-31T23:15:15-08:59", STRING, "2005-06-01T06:14:15-02:00");
TEST_SUCCESS_XML("a", "l", "2005-05-31T23:15:15-23:00", STRING, "2005-06-01T20:15:15-02:00");
@@ -105,51 +106,44 @@ test_data_xml(void **state)
/* fractional hours */
TEST_SUCCESS_XML("a", "l", "2005-05-25T23:15:15.88888+04:30", STRING, "2005-05-25T16:45:15.88888-02:00");
-#else
- /* Tests run with a TZ offset of +02:00, but this platform cannot represent that in time_t,
- * so libyang always returns unspecified TZ. */
- TEST_SUCCESS_XML("a", "l", "2005-05-25T23:15:15.88888Z", STRING, "2005-05-25T23:15:15.88888-00:00");
- TEST_SUCCESS_XML("a", "l", "2005-05-31T23:15:15-08:59", STRING, "2005-06-01T08:14:15-00:00");
- TEST_SUCCESS_XML("a", "l", "2005-05-31T23:15:15-23:00", STRING, "2005-06-01T22:15:15-00:00");
-
- /* test 1 second before epoch (mktime returns -1, but it is a correct value), with and without DST */
- TEST_SUCCESS_XML("a", "l", "1970-01-01T00:59:59-02:00", STRING, "1970-01-01T02:59:59-00:00");
- TEST_SUCCESS_XML("a", "l", "1969-12-31T23:59:59-02:00", STRING, "1970-01-01T01:59:59-00:00");
-
- /* canonize */
- TEST_SUCCESS_XML("a", "l", "2005-02-29T23:15:15-02:00", STRING, "2005-03-02T01:15:15-00:00");
-
- /* fractional hours */
- TEST_SUCCESS_XML("a", "l", "2005-05-25T23:15:15.88888+04:30", STRING, "2005-05-25T18:45:15.88888-00:00");
-#endif
/* unknown timezone -- timezone conversion MUST NOT happen */
TEST_SUCCESS_XML("a", "l", "2017-02-01T00:00:00-00:00", STRING, "2017-02-01T00:00:00-00:00");
TEST_SUCCESS_XML("a", "l", "2021-02-29T00:00:00-00:00", STRING, "2021-03-01T00:00:00-00:00");
- TEST_ERROR_XML("a", "l", "2005-05-31T23:15:15.-08:00");
+ TEST_ERROR_XML("a", "l", "2005-05-31T23:15:15.-08:00", LY_EVALID);
CHECK_LOG_CTX("Unsatisfied pattern - \"2005-05-31T23:15:15.-08:00\" does not conform to "
"\"\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[\\+\\-]\\d{2}:\\d{2})\".",
"Schema location \"/a:l\", line number 1.");
+ TEST_ERROR_XML("a", "l", "2023-16-15T20:13:01+01:00", LY_EINVAL);
+ CHECK_LOG_CTX("Invalid date-and-time month \"15\".", "Schema location \"/a:l\", line number 1.");
+
+ TEST_ERROR_XML("a", "l", "2023-10-15T20:13:01+95:00", LY_EINVAL);
+ CHECK_LOG_CTX("Invalid date-and-time timezone hour \"95\".", "Schema location \"/a:l\", line number 1.");
+
+ /* hex-string */
+ TEST_SUCCESS_XML("a", "l21", "DB:BA:12:54:fa", STRING, "db:ba:12:54:fa");
+ TEST_SUCCESS_XML("a", "l22", "f81D4fAE-7dec-11d0-A765-00a0c91E6BF6", STRING, "f81d4fae-7dec-11d0-a765-00a0c91e6bf6");
+
/* xpath1.0 */
- TEST_SUCCESS_XML("a\" xmlns:aa=\"urn:tests:a", "l2", "/aa:l2[. = '4']", STRING, "/a:l2[.='4']");
+ TEST_SUCCESS_XML("a\" xmlns:aa=\"urn:tests:a", "l3", "/aa:l3[. = '4']", STRING, "/a:l3[.='4']");
TEST_SUCCESS_XML("a\" xmlns:yl=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\" "
- "xmlns:ds=\"urn:ietf:params:xml:ns:yang:ietf-datastores", "l2",
+ "xmlns:ds=\"urn:ietf:params:xml:ns:yang:ietf-datastores", "l3",
"/yl:yang-library/yl:datastore/yl:name = 'ds:running'", STRING,
"/ietf-yang-library:yang-library/datastore/name='ietf-datastores:running'");
- TEST_SUCCESS_XML("a\" xmlns:a1=\"urn:tests:a\" xmlns:a2=\"urn:tests:a\" xmlns:bb=\"urn:tests:b", "l2",
+ TEST_SUCCESS_XML("a\" xmlns:a1=\"urn:tests:a\" xmlns:a2=\"urn:tests:a\" xmlns:bb=\"urn:tests:b", "l3",
"/a1:node1/a2:node2[a1:node3/bb:node4]/bb:node5 | bb:node6 and (bb:node7)", STRING,
"/a:node1/node2[node3/b:node4]/b:node5 | b:node6 and (b:node7)");
- TEST_SUCCESS_XML("a", "l2", "/l2[. = '4']", STRING, "/l2[.='4']");
-
- TEST_ERROR_XML("a", "l2", "/a:l2[. = '4']");
- CHECK_LOG_CTX("Failed to resolve prefix \"a\".", "Schema location \"/a:l2\", line number 1.");
- TEST_ERROR_XML("a\" xmlns:yl=\"urn:ietf:params:xml:ns:yang:ietf-yang-library", "l2",
- "/yl:yang-library/yl:datastore/yl::name");
- CHECK_LOG_CTX("Storing value failed.", "Schema location \"/a:l2\", line number 1.",
- "Invalid character 'y'[31] of expression '/yl:yang-library/yl:datastore/yl::name'.",
- "Schema location \"/a:l2\", line number 1.");
+ TEST_SUCCESS_XML("a", "l3", "/l3[. = '4']", STRING, "/l3[.='4']");
+
+ TEST_ERROR_XML("a", "l3", "/a:l3[. = '4']", LY_EVALID);
+ CHECK_LOG_CTX("Failed to resolve prefix \"a\".", "Schema location \"/a:l3\", line number 1.");
+ TEST_ERROR_XML("a\" xmlns:yl=\"urn:ietf:params:xml:ns:yang:ietf-yang-library", "l3",
+ "/yl:yang-library/yl:datastore/yl::name", LY_EVALID);
+ CHECK_LOG_CTX("Storing value failed.", "Schema location \"/a:l3\", line number 1.");
+ CHECK_LOG_CTX("Invalid character 'y'[31] of expression '/yl:yang-library/yl:datastore/yl::name'.",
+ "Schema location \"/a:l3\", line number 1.");
}
static void
@@ -191,6 +185,31 @@ test_print(void **state)
}
static void
+test_duplicate(void **state)
+{
+ const char *schema = MODULE_CREATE_YANG("a", "leaf l1 {type yang:date-and-time;} leaf l2 {type yang:xpath1.0;}");
+ const char *data, *expected;
+ struct lyd_node *tree, *dup;
+
+ UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
+
+ data = "<l1 xmlns=\"urn:tests:a\">2005-05-25T23:15:15.88888+04:30</l1>"
+ "<l2 xmlns=\"urn:tests:a\" xmlns:aa=\"urn:tests:a\">/aa:l2[. = '/aa:l2']</l2>";
+ CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
+
+ /* duplicate */
+ assert_int_equal(LY_SUCCESS, lyd_dup_siblings(tree, NULL, 0, &dup));
+
+ /* print */
+ expected = "<l1 xmlns=\"urn:tests:a\">2005-05-25T16:45:15.88888-02:00</l1>"
+ "<l2 xmlns=\"urn:tests:a\" xmlns:pref=\"urn:tests:a\">/pref:l2[.='/pref:l2']</l2>";
+ CHECK_LYD_STRING_PARAM(dup, expected, LYD_XML, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS);
+
+ lyd_free_siblings(tree);
+ lyd_free_siblings(dup);
+}
+
+static void
test_lyb(void **state)
{
const char *schema;
@@ -216,6 +235,7 @@ main(void)
const struct CMUnitTest tests[] = {
UTEST(test_data_xml),
UTEST(test_print),
+ UTEST(test_duplicate),
UTEST(test_lyb),
};
diff --git a/tests/utests/utests.h b/tests/utests/utests.h
index 877d048..0e0649d 100644
--- a/tests/utests/utests.h
+++ b/tests/utests/utests.h
@@ -1010,7 +1010,9 @@ struct utest_context {
LY_ARRAY_COUNT_TYPE arr_size = sizeof(VALUE) / sizeof(VALUE[0]); \
assert_int_equal(arr_size, LY_ARRAY_COUNT((NODE).target)); \
for (LY_ARRAY_COUNT_TYPE it = 0; it < arr_size; it++) { \
- assert_int_equal(VALUE[it], (NODE).target[it].pred_type); \
+ if ((NODE).target[it].predicates) { \
+ assert_int_equal(VALUE[it], (NODE).target[it].predicates[0].type); \
+ } \
} \
}
@@ -1224,97 +1226,32 @@ struct utest_context {
_UC->in = NULL
/**
- * @brief Internal macro to compare error info record with the expected error message and path.
- * If NULL is provided as MSG, no error info record (NULL) is expected.
+ * @brief Check expected last error message.
*
- * @param[in] ERR Error information record from libyang context.
* @param[in] MSG Expected error message.
- * @param[in] PATH Expected error path.
- */
-#define _CHECK_LOG_CTX(ERR, MSG, PATH) \
- if (!MSG) { \
- assert_null(ERR); \
- } else { \
- assert_non_null(ERR); \
- CHECK_STRING((ERR)->msg, MSG); \
- CHECK_STRING((ERR)->path, PATH); \
- }
-
-/**`
- * @brief Internal macro to check the last libyang's context error.
- */
-#define _CHECK_LOG_CTX1(MSG, PATH) \
- _CHECK_LOG_CTX(ly_err_last(_UC->ctx), MSG, PATH)
-
-/**
- * @brief Internal macro to check the last two libyang's context error.
- */
-#define _CHECK_LOG_CTX2(MSG1, PATH1, MSG2, PATH2) \
- _CHECK_LOG_CTX(ly_err_last(_UC->ctx), MSG1, PATH1); \
- _CHECK_LOG_CTX(ly_err_last(_UC->ctx)->prev, MSG2, PATH2)
-
-/**
- * @brief Internal macro to check the last three libyang's context error.
- */
-#define _CHECK_LOG_CTX3(MSG1, PATH1, MSG2, PATH2, MSG3, PATH3) \
- _CHECK_LOG_CTX2(MSG1, PATH1, MSG2, PATH2); \
- _CHECK_LOG_CTX(ly_err_last(_UC->ctx)->prev->prev, MSG3, PATH3)
-
-/**
- * @brief Internal macro to check the last three libyang's context error.
- */
-#define _CHECK_LOG_CTX4(MSG1, PATH1, MSG2, PATH2, MSG3, PATH3, MSG4, PATH4) \
- _CHECK_LOG_CTX3(MSG1, PATH1, MSG2, PATH2, MSG3, PATH3); \
- _CHECK_LOG_CTX(ly_err_last(_UC->ctx)->prev->prev->prev, MSG4, PATH4)
-
-/**
- * @brief Internal macro to check the last three libyang's context error.
- */
-#define _CHECK_LOG_CTX5(MSG1, PATH1, MSG2, PATH2, MSG3, PATH3, MSG4, PATH4, MSG5, PATH5) \
- _CHECK_LOG_CTX4(MSG1, PATH1, MSG2, PATH2, MSG3, PATH3, MSG4, PATH4); \
- _CHECK_LOG_CTX(ly_err_last(_UC->ctx)->prev->prev->prev->prev, MSG5, PATH5)
-
-/**
- * @brief Internal macro to check the last three libyang's context error.
- */
-#define _CHECK_LOG_CTX6(MSG1, PATH1, MSG2, PATH2, MSG3, PATH3, MSG4, PATH4, MSG5, PATH5, MSG6, PATH6) \
- _CHECK_LOG_CTX5(MSG1, PATH1, MSG2, PATH2, MSG3, PATH3, MSG4, PATH4, MSG5, PATH5); \
- _CHECK_LOG_CTX(ly_err_last(_UC->ctx)->prev->prev->prev->prev->prev, MSG6, PATH6)
-
-/**
- * @brief Internal macro to check the last three libyang's context error.
- */
-#define _CHECK_LOG_CTX7(MSG1, PATH1, MSG2, PATH2, MSG3, PATH3, MSG4, PATH4, MSG5, PATH5, MSG6, PATH6, MSG7, PATH7) \
- _CHECK_LOG_CTX6(MSG1, PATH1, MSG2, PATH2, MSG3, PATH3, MSG4, PATH4, MSG5, PATH5, MSG6, PATH6); \
- _CHECK_LOG_CTX(ly_err_last(_UC->ctx)->prev->prev->prev->prev->prev->prev, MSG7, PATH7)
-
-/**
- * @brief Internal macro to check the last three libyang's context error.
*/
-#define _CHECK_LOG_CTX8(MSG1, PATH1, MSG2, PATH2, MSG3, PATH3, MSG4, PATH4, MSG5, PATH5, MSG6, PATH6, MSG7, PATH7, MSG8, PATH8) \
- _CHECK_LOG_CTX7(MSG1, PATH1, MSG2, PATH2, MSG3, PATH3, MSG4, PATH4, MSG5, PATH5, MSG6, PATH6, MSG7, PATH7); \
- _CHECK_LOG_CTX(ly_err_last(_UC->ctx)->prev->prev->prev->prev->prev->prev->prev, MSG8, PATH8)
+#define CHECK_LOG_LASTMSG(MSG) \
+ CHECK_STRING(ly_last_errmsg(), MSG)
/**
- * @brief Internal helper macro to select _CHECK_LOG_CTX* macro according to the provided parameters.
- */
-#define _GET_CHECK_LOG_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, NAME, ...) NAME
-
-/**
- * @brief Check expected error(s) in libyang context.
- *
- * Macro has variadic parameters expected to be provided in pairs of error message and error path starting
- * from the latest error. Current limit is checking at most 3 last errors. After checking, macro cleans up
- * all the errors from the libyang context.
+ * @brief Check expected last error in libyang context, which is then cleared. Can be called repeatedly to check
+ * several errors. If NULL is provided as MSG, no error info record (NULL) is expected.
*
* @param[in] MSG Expected error message.
* @param[in] PATH Expected error path.
*/
-#define CHECK_LOG_CTX(...) \
- _GET_CHECK_LOG_MACRO(__VA_ARGS__, _CHECK_LOG_CTX8, _INVAL, _CHECK_LOG_CTX7, _INVAL, \
- _CHECK_LOG_CTX6, _INVAL, _CHECK_LOG_CTX5, _INVAL, _CHECK_LOG_CTX4, _INVAL, \
- _CHECK_LOG_CTX3, _INVAL, _CHECK_LOG_CTX2, _INVAL, _CHECK_LOG_CTX1, DUMMY)(__VA_ARGS__); \
- ly_err_clean(_UC->ctx, NULL)
+#define CHECK_LOG_CTX(MSG, PATH) \
+ { \
+ struct ly_err_item *_e = ly_err_last(_UC->ctx); \
+ if (!MSG) { \
+ assert_null(_e); \
+ } else { \
+ assert_non_null(_e); \
+ CHECK_STRING(_e->msg, MSG); \
+ CHECK_STRING(_e->path, PATH); \
+ } \
+ ly_err_clean(_UC->ctx, _e); \
+ }
/**
* @brief Check expected error in libyang context including error-app-tag.
@@ -1324,14 +1261,23 @@ struct utest_context {
* @param[in] APPTAG Expected error-app-tag.
*/
#define CHECK_LOG_CTX_APPTAG(MSG, PATH, APPTAG) \
- if (!MSG) { \
- assert_null(ly_err_last(_UC->ctx)); \
- } else { \
- assert_non_null(ly_err_last(_UC->ctx)); \
- CHECK_STRING(ly_err_last(_UC->ctx)->msg, MSG); \
- CHECK_STRING(ly_err_last(_UC->ctx)->path, PATH); \
- CHECK_STRING(ly_err_last(_UC->ctx)->apptag, APPTAG); \
- } \
+ { \
+ struct ly_err_item *_e = ly_err_last(_UC->ctx); \
+ if (!MSG) { \
+ assert_null(_e); \
+ } else { \
+ assert_non_null(_e); \
+ CHECK_STRING(_e->msg, MSG); \
+ CHECK_STRING(_e->path, PATH); \
+ CHECK_STRING(_e->apptag, APPTAG); \
+ } \
+ ly_err_clean(_UC->ctx, _e); \
+ }
+
+/**
+ * @brief Clear all errors stored in the libyang context.
+ */
+#define UTEST_LOG_CTX_CLEAN \
ly_err_clean(_UC->ctx, NULL)
/**
@@ -1435,7 +1381,8 @@ utest_teardown(void **state)
{
*state = NULL;
- /* libyang context */
+ /* libyang context, no leftover messages */
+ assert_null(ly_err_last(current_utest_context->ctx));
ly_ctx_destroy(current_utest_context->ctx);
if (current_utest_context->orig_tz) {
diff --git a/tests/yanglint/CMakeLists.txt b/tests/yanglint/CMakeLists.txt
new file mode 100644
index 0000000..c1e081a
--- /dev/null
+++ b/tests/yanglint/CMakeLists.txt
@@ -0,0 +1,36 @@
+if(WIN32)
+ set(YANGLINT_INTERACTIVE OFF)
+else()
+ set(YANGLINT_INTERACTIVE ON)
+endif()
+
+function(add_yanglint_test)
+ cmake_parse_arguments(ADDTEST "" "NAME;VIA;SCRIPT" "" ${ARGN})
+ set(TEST_NAME yanglint_${ADDTEST_NAME})
+
+ if(${ADDTEST_VIA} STREQUAL "tclsh")
+ set(WRAPPER ${PATH_TCLSH})
+ else()
+ message(FATAL_ERROR "build: unexpected wrapper '${ADDTEST_VIA}'")
+ endif()
+
+ add_test(NAME ${TEST_NAME} COMMAND ${WRAPPER} ${CMAKE_CURRENT_SOURCE_DIR}/${ADDTEST_SCRIPT})
+ set_property(TEST ${TEST_NAME} APPEND PROPERTY ENVIRONMENT "TESTS_DIR=${CMAKE_CURRENT_SOURCE_DIR}")
+ set_property(TEST ${TEST_NAME} APPEND PROPERTY ENVIRONMENT "YANG_MODULES_DIR=${CMAKE_CURRENT_SOURCE_DIR}/modules")
+ set_property(TEST ${TEST_NAME} APPEND PROPERTY ENVIRONMENT "YANGLINT=${PROJECT_BINARY_DIR}")
+endfunction(add_yanglint_test)
+
+if(ENABLE_TESTS)
+ # tests of interactive mode using tclsh
+ find_program(PATH_TCLSH NAMES tclsh)
+ if(NOT PATH_TCLSH)
+ message(WARNING "'tclsh' not found! The yanglint(1) interactive tests will not be available.")
+ else()
+ if(YANGLINT_INTERACTIVE)
+ add_yanglint_test(NAME interactive VIA tclsh SCRIPT interactive/all.tcl)
+ add_yanglint_test(NAME non-interactive VIA tclsh SCRIPT non-interactive/all.tcl)
+ else()
+ add_yanglint_test(NAME non-interactive VIA tclsh SCRIPT non-interactive/all.tcl)
+ endif()
+ endif()
+endif()
diff --git a/tests/yanglint/README.md b/tests/yanglint/README.md
new file mode 100644
index 0000000..6c51d89
--- /dev/null
+++ b/tests/yanglint/README.md
@@ -0,0 +1,107 @@
+# yanglint testing
+
+Testing yanglint is divided into two ways.
+It is either tested in interactive mode using the tcl command 'expect' or non-interactively, classically from the command line.
+For both modes, unit testing was used using the tcl package tcltest.
+
+## How to
+
+The sample commands in this chapter using `tclsh` are called in the `interactive` or `non-interactive` directories.
+
+### How to run all yanglint tests?
+
+In the build directory designated for cmake, enter:
+
+```
+ctest -R yanglint
+```
+
+### How to run all yanglint tests that are in interactive mode?
+
+In the interactive directory, run:
+
+```
+tclsh all.tcl
+```
+
+### How to run all yanglint tests that are in non-interactive mode?
+
+In the non-interactive directory, run:
+
+```
+tclsh all.tcl
+```
+
+### How to run all unit-tests from .test file?
+
+```
+tclsh clear.test
+```
+
+or alternatively:
+
+```
+tclsh all.tcl -file clear.test
+```
+
+### How to run one unit-test?
+
+```
+tclsh clear.test -match clear_ietf_yang_library
+```
+
+or alternatively:
+
+```
+tclsh all.tcl -file clear.test -match clear_ietf_yang_library
+```
+
+### How to run unit-tests for a certain yanglint command?
+
+Test names are assumed to consist of the command name:
+
+```
+tclsh all.tcl -match clear*
+```
+
+### How do I get more detailed information about 'expect' for a certain test?
+
+In the interactive directory, run:
+
+```
+tclsh clear.test -match clear_ietf_yang_library -load "exp_internal 1"
+```
+
+### How do I get more detailed dialog between 'expect' and yanglint for a certain test?
+
+In the interactive directory, run:
+
+```
+tclsh clear.test -match clear_ietf_yang_library -load "log_user 1"
+```
+
+### How do I suppress error message from tcltest?
+
+Probably only possible to do via `-verbose ""`
+
+### How can I also debug?
+
+You can write commands `interact` and `interpreter` from 'Expect' package into some test.
+However, the most useful are the `exp_internal` and `log_user`, which can also be written directly into the test.
+See also the rlwrap tool.
+You can also use other debugging methods used in tcl programming.
+
+### Are the tests between interactive mode and non-interactive mode similar?
+
+Sort of...
+- regex \n must be changed to \r\n in the tests for interactive yanglint
+
+### I would like to add a new "ly_" function.
+
+Add it to the ly.tcl file.
+If you need to call other subfunctions in it, add them to namespace ly::private.
+
+### I would like to use function other than those prefixed with "ly_".
+
+Look in the common.tcl file in the "uti" namespace,
+which contains general tcl functions that can be used in both interactive and non-interactive tests.
diff --git a/tests/yanglint/common.tcl b/tests/yanglint/common.tcl
new file mode 100644
index 0000000..d186282
--- /dev/null
+++ b/tests/yanglint/common.tcl
@@ -0,0 +1,114 @@
+# @brief Common functions and variables for yanglint-interactive and yanglint-non-interactive.
+#
+# The script requires variables:
+# ::env(TESTS_DIR) - Main test directory. Must be set if the script is run via ctest.
+#
+# The script sets the variables:
+# ::env(TESTS_DIR) - Main test directory. It is set by default if not defined.
+# ::env(YANG_MODULES_DIR) - Directory of YANG modules.
+# TUT_PATH - Assumed absolute path to the directory in which the TUT is located.
+# TUT_NAME - TUT name (without path).
+# ::tcltest::testConstraint ctest - A tcltest variable that is set to true if the script is run via ctest. Causes tests
+# to be a skipped.
+
+package require tcltest
+namespace import ::tcltest::test ::tcltest::cleanupTests
+
+# Set directory paths for testing yanglint.
+if { ![info exists ::env(TESTS_DIR)] } {
+ # the script is not run via 'ctest' so paths must be set
+ set ::env(TESTS_DIR) "../"
+ set ::env(YANG_MODULES_DIR) "../modules"
+ set TUT_PATH "../../../build"
+ ::tcltest::testConstraint ctest false
+} else {
+ # cmake (ctest) already sets ::env variables
+ set TUT_PATH $::env(YANGLINT)
+ ::tcltest::testConstraint ctest true
+}
+
+set TUT_NAME "yanglint"
+
+# The script continues by defining functions specific to the yanglint tool.
+
+namespace eval uti {
+ namespace export *
+}
+
+# Iterate through the items in the list 'lst' and return a new list where
+# the items will have the form: <prefix><item><suffix>.
+# Parameter 'index' determines at which index it will start wrapping.
+# Parameter 'step' specifies how far the iterator must move to wrap the next item.
+proc uti::wrap_list_items {lst {prefix ""} {suffix ""} {index 0} {step 1}} {
+ # counter to track when to insert wrapper
+ set cnt $step
+ set len [llength $lst]
+
+ if {$index > 0} {
+ # copy list from interval <0;$index)
+ set ret [lrange $lst 0 [expr {$index - 1}]]
+ } else {
+ set ret {}
+ }
+
+ for {set i $index} {$i < $len} {incr i} {
+ incr cnt
+ set item [lindex $lst $i]
+ if {$cnt >= $step} {
+ # insert wrapper for item
+ set cnt 0
+ lappend ret [string cat $prefix $item $suffix]
+ } else {
+ # just copy item
+ lappend ret $item
+ }
+ }
+
+ return $ret
+}
+
+# Wrap list items with xml tags.
+# The element format is: <tag>value</tag>
+# Parameter 'values' is list of values.
+# Parameter 'tag' is the name of the searched tag.
+proc uti::wrap_to_xml {values tag {index 0} {step 1}} {
+ return [wrap_list_items $values "<$tag>" "</$tag>" $index $step]
+}
+
+# Wrap list items with json attributes.
+# The pair format is: "attribute": "value"
+# Parameter 'values' is list of values.
+# Parameter 'attribute' is the name of the searched attribute.
+proc uti::wrap_to_json {values attribute {index 0} {step 1}} {
+ return [wrap_list_items $values "\"$attribute\": \"" "\"" $index $step]
+}
+
+# Convert list to a regex (which is just a string) so that 'delim' is between items,
+# 'begin' is at the beginning of the expression and 'end' is at the end.
+proc uti::list_to_regex {lst {delim ".*"} {begin ".*"} {end ".*"}} {
+ return [string cat $begin [join $lst $delim] $end]
+}
+
+# Merge two lists into one such that the nth items are merged into one separated by a delimiter.
+# Returns a list that is the same length as 'lst1' and 'lst2'
+proc uti::blend_lists {lst1 lst2 {delim ".*"}} {
+ return [lmap a $lst1 b $lst2 {string cat $a $delim $b}]
+}
+
+# Create regex to find xml elements.
+# The element format is: <tag>value</tag>
+# Parameter 'values' is list of values.
+# Parameter 'tag' is the name of the searched tag.
+# The resulting expression looks like: ".*<tag>value1</tag>.*<tag>value2</tag>.*..."
+proc uti::regex_xml_elements {values tag} {
+ return [list_to_regex [wrap_to_xml $values $tag]]
+}
+
+# Create regex to find json pairs.
+# The pair format is: "attribute": "value"
+# Parameter 'values' is list of values.
+# Parameter 'attribute' is the name of the searched attribute.
+# The resulting expression looks like: ".*\"attribute\": \"value1\".*\"attribute\": \"value2\".*..."
+proc uti::regex_json_pairs {values attribute} {
+ return [list_to_regex [wrap_to_json $values $attribute]]
+}
diff --git a/tests/yanglint/data/modaction.xml b/tests/yanglint/data/modaction.xml
new file mode 100644
index 0000000..37faa2d
--- /dev/null
+++ b/tests/yanglint/data/modaction.xml
@@ -0,0 +1,8 @@
+<con xmlns="urn:yanglint:modaction">
+ <ls>
+ <lfkey>kv</lfkey>
+ <act>
+ <lfi>some_input</lfi>
+ </act>
+ </ls>
+</con>
diff --git a/tests/yanglint/data/modaction_ds.xml b/tests/yanglint/data/modaction_ds.xml
new file mode 100644
index 0000000..a5a1727
--- /dev/null
+++ b/tests/yanglint/data/modaction_ds.xml
@@ -0,0 +1,5 @@
+<con xmlns="urn:yanglint:modaction">
+ <ls>
+ <lfkey>kv</lfkey>
+ </ls>
+</con>
diff --git a/tests/yanglint/data/modaction_nc.xml b/tests/yanglint/data/modaction_nc.xml
new file mode 100644
index 0000000..a74b6bf
--- /dev/null
+++ b/tests/yanglint/data/modaction_nc.xml
@@ -0,0 +1,13 @@
+<rpc message-id="101"
+ xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <action xmlns="urn:ietf:params:xml:ns:yang:1">
+ <con xmlns="urn:yanglint:modaction">
+ <ls>
+ <lfkey>kv</lfkey>
+ <act>
+ <lfi>some_input</lfi>
+ </act>
+ </ls>
+ </con>
+ </action>
+</rpc>
diff --git a/tests/yanglint/data/modaction_reply.xml b/tests/yanglint/data/modaction_reply.xml
new file mode 100644
index 0000000..7d6532d
--- /dev/null
+++ b/tests/yanglint/data/modaction_reply.xml
@@ -0,0 +1,8 @@
+<con xmlns="urn:yanglint:modaction">
+ <ls>
+ <lfkey>kv</lfkey>
+ <act>
+ <lfo>-56</lfo>
+ </act>
+ </ls>
+</con>
diff --git a/tests/yanglint/data/modaction_reply_nc.xml b/tests/yanglint/data/modaction_reply_nc.xml
new file mode 100644
index 0000000..f7c3b8f
--- /dev/null
+++ b/tests/yanglint/data/modaction_reply_nc.xml
@@ -0,0 +1,4 @@
+<rpc-reply message-id="101"
+ xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <lfo xmlns="urn:yanglint:modaction">-56</lfo>
+</rpc-reply>
diff --git a/tests/yanglint/data/modconfig.xml b/tests/yanglint/data/modconfig.xml
new file mode 100644
index 0000000..f8a03a9
--- /dev/null
+++ b/tests/yanglint/data/modconfig.xml
@@ -0,0 +1,4 @@
+<mcc xmlns="urn:yanglint:modconfig">
+ <lft>rw</lft>
+ <lff>ro</lff>
+</mcc>
diff --git a/tests/yanglint/data/modconfig2.xml b/tests/yanglint/data/modconfig2.xml
new file mode 100644
index 0000000..c96e344
--- /dev/null
+++ b/tests/yanglint/data/modconfig2.xml
@@ -0,0 +1,3 @@
+<mcc xmlns="urn:yanglint:modconfig">
+ <lft>rw</lft>
+</mcc>
diff --git a/tests/yanglint/data/modconfig_ctx.xml b/tests/yanglint/data/modconfig_ctx.xml
new file mode 100644
index 0000000..124989c
--- /dev/null
+++ b/tests/yanglint/data/modconfig_ctx.xml
@@ -0,0 +1,13 @@
+<yang-library xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library">
+ <module-set>
+ <name>main-set</name>
+ <module>
+ <name>modconfig</name>
+ <namespace>urn:yanglint:modconfig</namespace>
+ </module>
+ </module-set>
+ <content-id>1</content-id>
+</yang-library>
+<modules-state xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library">
+ <module-set-id>1</module-set-id>
+</modules-state>
diff --git a/tests/yanglint/data/moddatanodes.xml b/tests/yanglint/data/moddatanodes.xml
new file mode 100644
index 0000000..8ae6e97
--- /dev/null
+++ b/tests/yanglint/data/moddatanodes.xml
@@ -0,0 +1,17 @@
+<dnc xmlns="urn:yanglint:moddatanodes">
+ <lf>x</lf>
+ <lfl>1</lfl>
+ <lfl>2</lfl>
+ <con>
+ <lt>
+ <kalf>ka1</kalf>
+ <kblf>kb1</kblf>
+ <vlf>v1</vlf>
+ </lt>
+ <lt>
+ <kalf>ka2</kalf>
+ <kblf>kb2</kblf>
+ <vlf>v2</vlf>
+ </lt>
+ </con>
+</dnc>
diff --git a/tests/yanglint/data/moddefault.xml b/tests/yanglint/data/moddefault.xml
new file mode 100644
index 0000000..00f3a9d
--- /dev/null
+++ b/tests/yanglint/data/moddefault.xml
@@ -0,0 +1,4 @@
+<mdc xmlns="urn:yanglint:moddefault">
+ <lf>0</lf>
+ <di>5</di>
+</mdc>
diff --git a/tests/yanglint/data/modimp_type_ctx.xml b/tests/yanglint/data/modimp_type_ctx.xml
new file mode 100644
index 0000000..e6d158a
--- /dev/null
+++ b/tests/yanglint/data/modimp_type_ctx.xml
@@ -0,0 +1,13 @@
+<yang-library xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library">
+ <module-set>
+ <name>main-set</name>
+ <module>
+ <name>modimp-type</name>
+ <namespace>urn:yanglint:modimp-type</namespace>
+ </module>
+ </module-set>
+ <content-id>1</content-id>
+</yang-library>
+<modules-state xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library">
+ <module-set-id>1</module-set-id>
+</modules-state>
diff --git a/tests/yanglint/data/modleaf.djson b/tests/yanglint/data/modleaf.djson
new file mode 100644
index 0000000..25af218
--- /dev/null
+++ b/tests/yanglint/data/modleaf.djson
@@ -0,0 +1,3 @@
+{
+ "modleaf:lfl": 7
+}
diff --git a/tests/yanglint/data/modleaf.dxml b/tests/yanglint/data/modleaf.dxml
new file mode 100644
index 0000000..408936a
--- /dev/null
+++ b/tests/yanglint/data/modleaf.dxml
@@ -0,0 +1 @@
+<lfl xmlns="urn:yanglint:modleaf">7</lfl>
diff --git a/tests/yanglint/data/modleaf.xml b/tests/yanglint/data/modleaf.xml
new file mode 100644
index 0000000..408936a
--- /dev/null
+++ b/tests/yanglint/data/modleaf.xml
@@ -0,0 +1 @@
+<lfl xmlns="urn:yanglint:modleaf">7</lfl>
diff --git a/tests/yanglint/data/modleafref.xml b/tests/yanglint/data/modleafref.xml
new file mode 100644
index 0000000..c9fb147
--- /dev/null
+++ b/tests/yanglint/data/modleafref.xml
@@ -0,0 +1,2 @@
+<lfl xmlns="urn:yanglint:modleaf">7</lfl>
+<lfr xmlns="urn:yanglint:modleafref">7</lfr>
diff --git a/tests/yanglint/data/modleafref2.xml b/tests/yanglint/data/modleafref2.xml
new file mode 100644
index 0000000..3946daf
--- /dev/null
+++ b/tests/yanglint/data/modleafref2.xml
@@ -0,0 +1,2 @@
+<lfl xmlns="urn:yanglint:modleaf">7</lfl>
+<lfr xmlns="urn:yanglint:modleafref">10</lfr>
diff --git a/tests/yanglint/data/modmandatory.xml b/tests/yanglint/data/modmandatory.xml
new file mode 100644
index 0000000..108cb2a
--- /dev/null
+++ b/tests/yanglint/data/modmandatory.xml
@@ -0,0 +1,3 @@
+<mmc xmlns="urn:yanglint:modmandatory">
+ <lft>9</lft>
+</mmc>
diff --git a/tests/yanglint/data/modmandatory_invalid.xml b/tests/yanglint/data/modmandatory_invalid.xml
new file mode 100644
index 0000000..de71895
--- /dev/null
+++ b/tests/yanglint/data/modmandatory_invalid.xml
@@ -0,0 +1,3 @@
+<mmc xmlns="urn:yanglint:modmandatory">
+ <lff>9</lff>
+</mmc>
diff --git a/tests/yanglint/data/modmerge.xml b/tests/yanglint/data/modmerge.xml
new file mode 100644
index 0000000..b52eff5
--- /dev/null
+++ b/tests/yanglint/data/modmerge.xml
@@ -0,0 +1,4 @@
+<mmc xmlns="urn:yanglint:modmerge">
+ <en>one</en>
+ <lm>4</lm>
+</mmc>
diff --git a/tests/yanglint/data/modmerge2.xml b/tests/yanglint/data/modmerge2.xml
new file mode 100644
index 0000000..e7f17c4
--- /dev/null
+++ b/tests/yanglint/data/modmerge2.xml
@@ -0,0 +1,3 @@
+<mmc xmlns="urn:yanglint:modmerge">
+ <en>zero</en>
+</mmc>
diff --git a/tests/yanglint/data/modmerge3.xml b/tests/yanglint/data/modmerge3.xml
new file mode 100644
index 0000000..6ef857e
--- /dev/null
+++ b/tests/yanglint/data/modmerge3.xml
@@ -0,0 +1,3 @@
+<mmc xmlns="urn:yanglint:modmerge">
+ <lf>str</lf>
+</mmc>
diff --git a/tests/yanglint/data/modnotif.xml b/tests/yanglint/data/modnotif.xml
new file mode 100644
index 0000000..81cab21
--- /dev/null
+++ b/tests/yanglint/data/modnotif.xml
@@ -0,0 +1,5 @@
+<con xmlns="urn:yanglint:modnotif">
+ <nfn>
+ <lf>nested</lf>
+ </nfn>
+</con>
diff --git a/tests/yanglint/data/modnotif2.xml b/tests/yanglint/data/modnotif2.xml
new file mode 100644
index 0000000..fc75b57
--- /dev/null
+++ b/tests/yanglint/data/modnotif2.xml
@@ -0,0 +1,3 @@
+<nfg xmlns="urn:yanglint:modnotif">
+ <lf>top</lf>
+</nfg>
diff --git a/tests/yanglint/data/modnotif2_nc.xml b/tests/yanglint/data/modnotif2_nc.xml
new file mode 100644
index 0000000..c87cfa0
--- /dev/null
+++ b/tests/yanglint/data/modnotif2_nc.xml
@@ -0,0 +1,6 @@
+<notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
+ <eventTime>2010-12-06T08:00:01Z</eventTime>
+ <nfg xmlns="urn:yanglint:modnotif">
+ <lf>top</lf>
+ </nfg>
+</notification>
diff --git a/tests/yanglint/data/modnotif_ds.xml b/tests/yanglint/data/modnotif_ds.xml
new file mode 100644
index 0000000..efd835b
--- /dev/null
+++ b/tests/yanglint/data/modnotif_ds.xml
@@ -0,0 +1 @@
+<con xmlns="urn:yanglint:modnotif"></con>
diff --git a/tests/yanglint/data/modnotif_nc.xml b/tests/yanglint/data/modnotif_nc.xml
new file mode 100644
index 0000000..39a3440
--- /dev/null
+++ b/tests/yanglint/data/modnotif_nc.xml
@@ -0,0 +1,8 @@
+<notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
+ <eventTime>2010-12-06T08:00:01Z</eventTime>
+ <con xmlns="urn:yanglint:modnotif">
+ <nfn>
+ <lf>nested</lf>
+ </nfn>
+ </con>
+</notification>
diff --git a/tests/yanglint/data/modoper_leafref_action.xml b/tests/yanglint/data/modoper_leafref_action.xml
new file mode 100644
index 0000000..7ccf29f
--- /dev/null
+++ b/tests/yanglint/data/modoper_leafref_action.xml
@@ -0,0 +1,8 @@
+<cond xmlns="urn:yanglint:modoper-leafref">
+ <list>
+ <klf>key_val</klf>
+ <act>
+ <lfi>rw</lfi>
+ </act>
+ </list>
+</cond>
diff --git a/tests/yanglint/data/modoper_leafref_action_reply.xml b/tests/yanglint/data/modoper_leafref_action_reply.xml
new file mode 100644
index 0000000..39ec672
--- /dev/null
+++ b/tests/yanglint/data/modoper_leafref_action_reply.xml
@@ -0,0 +1,8 @@
+<cond xmlns="urn:yanglint:modoper-leafref">
+ <list>
+ <klf>key_val</klf>
+ <act>
+ <lfo>rw</lfo>
+ </act>
+ </list>
+</cond>
diff --git a/tests/yanglint/data/modoper_leafref_ds.xml b/tests/yanglint/data/modoper_leafref_ds.xml
new file mode 100644
index 0000000..f934b9b
--- /dev/null
+++ b/tests/yanglint/data/modoper_leafref_ds.xml
@@ -0,0 +1,9 @@
+<mcc xmlns="urn:yanglint:modconfig">
+ <lft>rw</lft>
+ <lff>ro</lff>
+</mcc>
+<cond xmlns="urn:yanglint:modoper-leafref">
+ <list>
+ <klf>key_val</klf>
+ </list>
+</cond>
diff --git a/tests/yanglint/data/modoper_leafref_notif.xml b/tests/yanglint/data/modoper_leafref_notif.xml
new file mode 100644
index 0000000..2c56b67
--- /dev/null
+++ b/tests/yanglint/data/modoper_leafref_notif.xml
@@ -0,0 +1,3 @@
+<notifg xmlns="urn:yanglint:modoper-leafref">
+ <lfr>rw</lfr>
+</notifg>
diff --git a/tests/yanglint/data/modoper_leafref_notif2.xml b/tests/yanglint/data/modoper_leafref_notif2.xml
new file mode 100644
index 0000000..466697c
--- /dev/null
+++ b/tests/yanglint/data/modoper_leafref_notif2.xml
@@ -0,0 +1,8 @@
+<cond xmlns="urn:yanglint:modoper-leafref">
+ <list>
+ <klf>key_val</klf>
+ <notif>
+ <lfn>rw</lfn>
+ </notif>
+ </list>
+</cond>
diff --git a/tests/yanglint/data/modoper_leafref_notif_err.xml b/tests/yanglint/data/modoper_leafref_notif_err.xml
new file mode 100644
index 0000000..1622ded
--- /dev/null
+++ b/tests/yanglint/data/modoper_leafref_notif_err.xml
@@ -0,0 +1,7 @@
+<mcc xmlns="urn:yanglint:modconfig">
+ <lft>rw</lft>
+ <lff>ro</lff>
+</mcc>
+<notifg xmlns="urn:yanglint:modoper-leafref">
+ <lf>rw</lf>
+</notifg>
diff --git a/tests/yanglint/data/modoper_leafref_rpc.xml b/tests/yanglint/data/modoper_leafref_rpc.xml
new file mode 100644
index 0000000..b294544
--- /dev/null
+++ b/tests/yanglint/data/modoper_leafref_rpc.xml
@@ -0,0 +1,3 @@
+<rpcg xmlns="urn:yanglint:modoper-leafref">
+ <lfi>rw</lfi>
+</rpcg>
diff --git a/tests/yanglint/data/modoper_leafref_rpc_reply.xml b/tests/yanglint/data/modoper_leafref_rpc_reply.xml
new file mode 100644
index 0000000..e8f7af3
--- /dev/null
+++ b/tests/yanglint/data/modoper_leafref_rpc_reply.xml
@@ -0,0 +1,5 @@
+<rpcg xmlns="urn:yanglint:modoper-leafref">
+ <cono>
+ <lfo>rw</lfo>
+ </cono>
+</rpcg>
diff --git a/tests/yanglint/data/modrpc.xml b/tests/yanglint/data/modrpc.xml
new file mode 100644
index 0000000..a4f924d
--- /dev/null
+++ b/tests/yanglint/data/modrpc.xml
@@ -0,0 +1,3 @@
+<rpc xmlns="urn:yanglint:modrpc">
+ <lfi>some_input</lfi>
+</rpc>
diff --git a/tests/yanglint/data/modrpc_nc.xml b/tests/yanglint/data/modrpc_nc.xml
new file mode 100644
index 0000000..78d3149
--- /dev/null
+++ b/tests/yanglint/data/modrpc_nc.xml
@@ -0,0 +1,6 @@
+<rpc message-id="101"
+ xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <rpc xmlns="urn:yanglint:modrpc">
+ <lfi>some_input</lfi>
+ </rpc>
+</rpc>
diff --git a/tests/yanglint/data/modrpc_reply.xml b/tests/yanglint/data/modrpc_reply.xml
new file mode 100644
index 0000000..632971c
--- /dev/null
+++ b/tests/yanglint/data/modrpc_reply.xml
@@ -0,0 +1,5 @@
+<rpc xmlns="urn:yanglint:modrpc">
+ <con>
+ <lfo>-56</lfo>
+ </con>
+</rpc>
diff --git a/tests/yanglint/data/modrpc_reply_nc.xml b/tests/yanglint/data/modrpc_reply_nc.xml
new file mode 100644
index 0000000..da2a01c
--- /dev/null
+++ b/tests/yanglint/data/modrpc_reply_nc.xml
@@ -0,0 +1,6 @@
+<rpc-reply message-id="101"
+ xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <con xmlns="urn:yanglint:modrpc">
+ <lfo>-56</lfo>
+ </con>
+</rpc-reply>
diff --git a/tests/yanglint/data/modsm.xml b/tests/yanglint/data/modsm.xml
new file mode 100644
index 0000000..bb0793c
--- /dev/null
+++ b/tests/yanglint/data/modsm.xml
@@ -0,0 +1,3 @@
+<root xmlns="urn:yanglint:modsm">
+ <lfl xmlns="urn:yanglint:modleaf">7</lfl>
+</root>
diff --git a/tests/yanglint/data/modsm2.xml b/tests/yanglint/data/modsm2.xml
new file mode 100644
index 0000000..ff6f103
--- /dev/null
+++ b/tests/yanglint/data/modsm2.xml
@@ -0,0 +1,4 @@
+<root xmlns="urn:yanglint:modsm">
+ <lfl xmlns="urn:yanglint:modleaf">7</lfl>
+ <alf xmlns="urn:yanglint:modsm-augment">str</alf>
+</root>
diff --git a/tests/yanglint/data/modsm_ctx_ext.xml b/tests/yanglint/data/modsm_ctx_ext.xml
new file mode 100644
index 0000000..e80141a
--- /dev/null
+++ b/tests/yanglint/data/modsm_ctx_ext.xml
@@ -0,0 +1,20 @@
+<yang-library xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library">
+ <module-set>
+ <name>test-set</name>
+ <module>
+ <name>modleaf</name>
+ <namespace>urn:yanglint:modleaf</namespace>
+ </module>
+ </module-set>
+ <content-id>1</content-id>
+</yang-library>
+<modules-state xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library">
+ <module-set-id>1</module-set-id>
+</modules-state>
+<schema-mounts xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount">
+ <mount-point>
+ <module>modsm</module>
+ <label>root</label>
+ <inline></inline>
+ </mount-point>
+</schema-mounts>
diff --git a/tests/yanglint/data/modsm_ctx_main.xml b/tests/yanglint/data/modsm_ctx_main.xml
new file mode 100644
index 0000000..5405d4d
--- /dev/null
+++ b/tests/yanglint/data/modsm_ctx_main.xml
@@ -0,0 +1,17 @@
+<yang-library xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library">
+ <module-set>
+ <name>main-set</name>
+ <module>
+ <name>modsm</name>
+ <namespace>urn:yanglint:modsm</namespace>
+ </module>
+ <module>
+ <name>modsm-augment</name>
+ <namespace>urn:yanglint:modsm-augment</namespace>
+ </module>
+ </module-set>
+ <content-id>1</content-id>
+</yang-library>
+<modules-state xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library">
+ <module-set-id>1</module-set-id>
+</modules-state>
diff --git a/tests/yanglint/interactive/add.test b/tests/yanglint/interactive/add.test
new file mode 100644
index 0000000..d1cacc1
--- /dev/null
+++ b/tests/yanglint/interactive/add.test
@@ -0,0 +1,59 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir $::env(YANG_MODULES_DIR)
+
+test add_basic {} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "add $mdir/modleafref.yang"
+ ly_cmd "list" "I modleafref\r.*I modleaf"
+}}
+
+test add_disable_searchdir_once {add --disable-searchdir} {
+-setup $ly_setup -cleanup $ly_cleanup -constraints {!ctest} -body {
+ ly_cmd "add $mdir/modimp-cwd.yang"
+ ly_cmd "clear"
+ ly_cmd_err "add -D $mdir/modimp-cwd.yang" "not found in local searchdirs"
+}}
+
+test add_disable_searchdir_twice {add -D -D} {
+-setup $ly_setup -cleanup $ly_cleanup -constraints {!ctest} -body {
+ ly_cmd "add $mdir/ietf-ip.yang"
+ ly_cmd "clear"
+ ly_cmd_err "add -D -D $mdir/ietf-ip.yang" "Loading \"ietf-interfaces\" module failed."
+}}
+
+test add_with_feature {Add module with feature} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "add --feature modfeature:ftr2 $mdir/modfeature.yang"
+ ly_cmd "feature -a" "modfeature:\r\n\tftr1 \\(off\\)\r\n\tftr2 \\(on\\)"
+}}
+
+test add_make_implemented_once {add --make-implemented} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_ignore "add $mdir/modmust.yang"
+ ly_cmd "list" "I modmust\r.*i modleaf"
+ ly_cmd "clear"
+ ly_ignore "add -i $mdir/modmust.yang"
+ ly_cmd "list" "I modmust\r.*I modleaf"
+}}
+
+test add_make_implemented_twice {add -i -i} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "add $mdir/modimp-type.yang"
+ ly_cmd "list" "I modimp-type\r.*i modtypedef"
+ ly_cmd "clear"
+ ly_cmd "add -i -i $mdir/modimp-type.yang"
+ ly_cmd "list" "I modimp-type\r.*I modtypedef"
+}}
+
+test add_extended_leafref_enabled {Valid module with --extended-leafref option} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "add -X $mdir/modextleafref.yang"
+}}
+
+test add_extended_leafref_disabled {Expected error if --extended-leafref is not set} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd_err "add $mdir/modextleafref.yang" "Unexpected XPath token \"FunctionName\""
+}}
+
+cleanupTests
diff --git a/tests/yanglint/interactive/all.tcl b/tests/yanglint/interactive/all.tcl
new file mode 100644
index 0000000..b22a5ab
--- /dev/null
+++ b/tests/yanglint/interactive/all.tcl
@@ -0,0 +1,15 @@
+package require tcltest
+
+# Hook to determine if any of the tests failed.
+# Sets a global variable exitCode to 1 if any test fails otherwise it is set to 0.
+proc tcltest::cleanupTestsHook {} {
+ variable numTests
+ set ::exitCode [expr {$numTests(Failed) > 0}]
+}
+
+if {[info exists ::env(TESTS_DIR)]} {
+ tcltest::configure -testdir "$env(TESTS_DIR)/interactive"
+}
+
+tcltest::runAllTests
+exit $exitCode
diff --git a/tests/yanglint/interactive/clear.test b/tests/yanglint/interactive/clear.test
new file mode 100644
index 0000000..cac0810
--- /dev/null
+++ b/tests/yanglint/interactive/clear.test
@@ -0,0 +1,53 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir $::env(YANG_MODULES_DIR)
+set ddir $::env(TESTS_DIR)/data
+
+test clear_searchpath {searchpath is also deleted} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "searchpath ./"
+ ly_cmd "clear"
+ ly_cmd "searchpath" "List of the searchpaths:" -ex
+}}
+
+test clear_make_implemented_once {clear --make-implemented} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "clear -i"
+ ly_cmd "add $mdir/modmust.yang"
+ ly_cmd "list" "I modmust\r.*I modleaf"
+}}
+
+test clear_make_implemented_twice {clear -i -i} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "clear -i -i"
+ ly_cmd "add $mdir/modmust.yang"
+ ly_cmd "list" "I modmust\r.*I modleaf"
+}}
+
+test clear_ietf_yang_library {clear --yang-library} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ # add models
+ ly_cmd "clear -y"
+ ly_cmd "list" "I ietf-yang-library"
+}}
+
+test clear_ylf_list {apply --yang-library-file and check result by --list} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "clear -Y $ddir/modimp_type_ctx.xml"
+ ly_cmd "list" "I modimp-type.*i modtypedef"
+}}
+
+test clear_ylf_make_implemented {apply --yang-library-file and --make-implemented} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "clear -Y $ddir/modimp_type_ctx.xml -i -i"
+ ly_cmd "list" "I modimp-type.*I modtypedef"
+}}
+
+test clear_ylf_augment_ctx {Setup context by yang-library-file and augment module} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "clear -Y $ddir/modconfig_ctx.xml"
+ ly_cmd "add $mdir/modconfig-augment.yang"
+ ly_cmd "print -f tree modconfig" "mca:alf"
+}}
+
+cleanupTests
diff --git a/tests/yanglint/interactive/completion.test b/tests/yanglint/interactive/completion.test
new file mode 100644
index 0000000..86ded1f
--- /dev/null
+++ b/tests/yanglint/interactive/completion.test
@@ -0,0 +1,69 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir "$::env(YANG_MODULES_DIR)"
+
+variable ly_cleanup {
+ ly_ignore
+ ly_exit
+}
+
+test completion_hints_ietf_ip {Completion and hints for ietf-ip.yang} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "add $mdir/ietf-ip.yang"
+
+ # completion and hint
+ ly_completion "print -f info -P " "print -f info -P /ietf-"
+
+ set hints {"/ietf-yang-schema-mount:schema-mounts" "/ietf-interfaces:interfaces" "/ietf-interfaces:interfaces-state"}
+ ly_hint "" "print -f info -P /ietf-" $hints
+
+ # double completion
+ ly_completion "i" "print -f info -P /ietf-interfaces:interfaces"
+ ly_completion "/" "print -f info -P /ietf-interfaces:interfaces/interface"
+
+ # a lot of hints
+ set hints {"/ietf-interfaces:interfaces/interface"
+ "/ietf-interfaces:interfaces/interface/name" "/ietf-interfaces:interfaces/interface/description"
+ "/ietf-interfaces:interfaces/interface/type" "/ietf-interfaces:interfaces/interface/enabled"
+ "/ietf-interfaces:interfaces/interface/link-up-down-trap-enable"
+ "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4" "/ietf-interfaces:interfaces/interface/ietf-ip:ipv6"
+ }
+ ly_hint "" "print -f info -P /ietf-interfaces:interfaces/interface" $hints
+
+ # double tab
+ ly_completion "/i" "print -f info -P /ietf-interfaces:interfaces/interface/ietf-ip:ipv"
+ ly_completion "4" "print -f info -P /ietf-interfaces:interfaces/interface/ietf-ip:ipv4"
+ set hints { "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4" "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/enabled"
+ "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/forwarding" "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/mtu"
+ "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address" "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/neighbor"
+ }
+ ly_hint "\t" "print -f info -P /ietf-interfaces:interfaces/interface/ietf-ip:ipv" $hints
+
+ # no more completion
+ ly_completion "/e" "print -f info -P /ietf-interfaces:interfaces/interface/ietf-ip:ipv4/enabled "
+}}
+
+# Note that somehow a command is automatically sent again (\t\t replaced by \r) after the hints.
+# But that doesn't affect the test because the tests only focus on the word in the hint.
+
+test hint_data_file {Show file hints for command data} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_hint "data $mdir\t\t" "data $mdir" "modleaf.yang.*"
+}}
+
+test hint_data_format {Show print hints for command data --format} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_hint "data -f \t\t" "data -f " "xml.*"
+}}
+
+test hint_data_file_after_opt {Show file hints after option with argument} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_hint "data -f xml $mdir\t\t" "data -f xml $mdir" "modleaf.yang.*"
+}}
+
+test hint_data_file_after_opt2 {Show file hints after option without argument} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_hint "data -m $mdir\t\t" "data -m $mdir" "modleaf.yang.*"
+}}
+
+cleanupTests
diff --git a/tests/yanglint/interactive/data_default.test b/tests/yanglint/interactive/data_default.test
new file mode 100644
index 0000000..1953acc
--- /dev/null
+++ b/tests/yanglint/interactive/data_default.test
@@ -0,0 +1,41 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+
+set mods "ietf-netconf-with-defaults moddefault"
+set data "$::env(TESTS_DIR)/data/moddefault.xml"
+
+test data_default_not_set {Print data without --default parameter} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load $mods"
+ ly_cmd "data -f xml $data" "</lf>.*</di>\r\n</mdc>"
+ ly_cmd "data -f json $data" "lf\".*di\"\[^\"]*"
+}}
+
+test data_default_all {data --default all} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load $mods"
+ ly_cmd "data -d all -f xml $data" "</lf>.*</di>.*</ds>\r\n</mdc>"
+ ly_cmd "data -d all -f json $data" "lf\".*di\".*ds\"\[^\"]*"
+}}
+
+test data_default_all_tagged {data --default all-tagged} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load $mods"
+ ly_cmd "data -d all-tagged -f xml $data" "</lf>.*<di.*default.*</di>.*<ds.*default.*</ds>\r\n</mdc>"
+ ly_cmd "data -d all-tagged -f json $data" "lf\".*di\".*ds\".*@ds\".*default\"\[^\"]*"
+}}
+
+test data_default_trim {data --default trim} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load $mods"
+ ly_cmd "data -d trim -f xml $data" "</lf>\r\n</mdc>"
+ ly_cmd "data -d trim -f json $data" "lf\"\[^\"]*"
+}}
+
+test data_default_implicit_tagged {data --default implicit-tagged} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load $mods"
+ ly_cmd "data -d implicit-tagged -f xml $data" "</lf>.*<di>5</di>.*<ds.*default.*</ds>\r\n</mdc>"
+ ly_cmd "data -d implicit-tagged -f json $data" "lf\".*di\"\[^@]*ds\".*default\"\[^\"]*"
+}}
+
+cleanupTests
diff --git a/tests/yanglint/interactive/data_format.test b/tests/yanglint/interactive/data_format.test
new file mode 100644
index 0000000..dc4b7e0
--- /dev/null
+++ b/tests/yanglint/interactive/data_format.test
@@ -0,0 +1,23 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+
+set ddir "$::env(TESTS_DIR)/data"
+
+test data_format_xml {Print data in xml format} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modleaf"
+ ly_cmd "data -f xml $ddir/modleaf.xml" "<lfl xmlns=\"urn:yanglint:modleaf\">7</lfl>"
+}}
+
+test data_format_json {Print data in json format} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modleaf"
+ ly_cmd "data -f json $ddir/modleaf.xml" "{\r\n \"modleaf:lfl\": 7\r\n}"
+}}
+
+test data_format_lyb_err {Print data in lyb format} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modleaf"
+ ly_cmd_err "data -f lyb $ddir/modleaf.xml" "The LYB format requires the -o"
+}}
+
+cleanupTests
diff --git a/tests/yanglint/interactive/data_in_format.test b/tests/yanglint/interactive/data_in_format.test
new file mode 100644
index 0000000..cc5f37e
--- /dev/null
+++ b/tests/yanglint/interactive/data_in_format.test
@@ -0,0 +1,21 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+
+set ddir "$::env(TESTS_DIR)/data"
+
+test data_in_format_xml {--in-format xml} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modleaf"
+ ly_cmd "data -F xml $ddir/modleaf.dxml"
+ ly_cmd_err "data -F json $ddir/modleaf.dxml" "Failed to parse"
+ ly_cmd_err "data -F lyb $ddir/modleaf.dxml" "Failed to parse"
+}}
+
+test data_in_format_json {--in-format json} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modleaf"
+ ly_cmd "data -F json $ddir/modleaf.djson"
+ ly_cmd_err "data -F xml $ddir/modleaf.djson" "Failed to parse"
+ ly_cmd_err "data -F lyb $ddir/modleaf.djson" "Failed to parse"
+}}
+
+cleanupTests
diff --git a/tests/yanglint/interactive/data_merge.test b/tests/yanglint/interactive/data_merge.test
new file mode 100644
index 0000000..38754c7
--- /dev/null
+++ b/tests/yanglint/interactive/data_merge.test
@@ -0,0 +1,33 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+
+set ddir "$::env(TESTS_DIR)/data"
+
+test data_merge_basic {Data is merged and the node is added} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modmerge"
+ ly_cmd "data -m -f xml $ddir/modmerge.xml $ddir/modmerge3.xml" "<en>.*<lm>.*<lf>"
+}}
+
+test data_merge_validation_failed {Data is merged but validation failed.} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modmerge"
+ ly_cmd "data $ddir/modmerge.xml"
+ ly_cmd "data $ddir/modmerge2.xml"
+ ly_cmd "data -m $ddir/modmerge2.xml $ddir/modmerge.xml"
+ ly_cmd_err "data -m $ddir/modmerge.xml $ddir/modmerge2.xml" "Merged data are not valid"
+}}
+
+test data_merge_dataconfig {The merge option has effect only for 'data' and 'config' TYPEs} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modrpc modnotif modconfig modleaf"
+ set wrn1 "option has effect only for"
+ ly_cmd_wrn "data -m -t rpc $ddir/modrpc.xml $ddir/modrpc.xml" $wrn1
+ ly_cmd_wrn "data -m -t notif $ddir/modnotif2.xml $ddir/modnotif2.xml" $wrn1
+ ly_cmd_wrn "data -m -t get $ddir/modleaf.xml $ddir/modconfig.xml" $wrn1
+ ly_cmd_wrn "data -m -t getconfig $ddir/modleaf.xml $ddir/modconfig2.xml" $wrn1
+ ly_cmd_wrn "data -m -t edit $ddir/modleaf.xml $ddir/modconfig2.xml" $wrn1
+ ly_cmd "data -m -t config $ddir/modleaf.xml $ddir/modconfig2.xml"
+ ly_cmd "data -m -t data $ddir/modleaf.xml $ddir/modconfig.xml"
+}}
+
+cleanupTests
diff --git a/tests/yanglint/interactive/data_not_strict.test b/tests/yanglint/interactive/data_not_strict.test
new file mode 100644
index 0000000..201a5a9
--- /dev/null
+++ b/tests/yanglint/interactive/data_not_strict.test
@@ -0,0 +1,25 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+
+set ddir $::env(TESTS_DIR)/data
+
+test data_no_strict_basic {} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modleaf"
+ ly_cmd_err "data $ddir/modmandatory.xml" "No module with namespace \"urn:yanglint:modmandatory\" in the context."
+ ly_cmd "data -n $ddir/modmandatory.xml"
+}}
+
+test data_no_strict_invalid_data {validation with --no-strict but data are invalid} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ set errmsg "Mandatory node \"lft\" instance does not exist."
+ ly_cmd "load modmandatory"
+ ly_cmd_err "data -n $ddir/modmandatory_invalid.xml" $errmsg
+}}
+
+test data_no_strict_ignore_invalid_data {--no-strict ignore invalid data if no schema is provided} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modleaf"
+ ly_cmd "data -f xml -n $ddir/modmandatory_invalid.xml $ddir/modleaf.xml" "modleaf.*</lfl>$"
+}}
+
+cleanupTests
diff --git a/tests/yanglint/interactive/data_operational.test b/tests/yanglint/interactive/data_operational.test
new file mode 100644
index 0000000..c0c7b1c
--- /dev/null
+++ b/tests/yanglint/interactive/data_operational.test
@@ -0,0 +1,86 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+
+set ddir "$::env(TESTS_DIR)/data"
+set err1 "Operational datastore takes effect only with RPCs/Actions/Replies/Notification input data types"
+
+test data_operational_twice {it is not allowed to specify more than one --operational parameter} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modoper-leafref"
+ ly_cmd "data -t notif -O $ddir/modconfig.xml -O $ddir/modleaf.xml" "cannot be set multiple times"
+}}
+
+test data_operational_no_type {--operational should be with parameter --type} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modoper-leafref"
+ ly_cmd_wrn "data -O $ddir/modconfig.xml $ddir/modoper_leafref_notif.xml" $err1
+}}
+
+test data_operational_missing {--operational is omitted and the datastore contents is in the data file} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modoper-leafref"
+ ly_cmd_err "data $ddir/modoper_leafref_notif_err.xml" "Failed to parse input data file"
+}}
+
+test data_operational_wrong_type {data are not defined as an operation} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd_wrn "data -t data -O $ddir/modconfig.xml $ddir/modleaf.xml" $err1
+}}
+
+test data_operational_datastore_with_unknown_data {unknown data are ignored} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modrpc"
+ ly_cmd "data -t rpc -O $ddir/modmandatory_invalid.xml $ddir/modrpc.xml"
+}}
+
+test data_operational_empty_datastore {datastore is considered empty because it contains unknown data} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modrpc modnotif"
+ ly_cmd "data -t rpc -O $ddir/modmandatory_invalid.xml $ddir/modrpc.xml"
+ set msg "parent \"/modnotif:con\" not found in the operational data"
+ ly_cmd_err "data -t notif -O $ddir/modmandatory_invalid.xml $ddir/modnotif.xml" $msg
+}}
+
+test data_operational_notif_leafref {--operational data is referenced from notification-leafref} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modoper-leafref"
+ ly_cmd "data -t notif -O $ddir/modconfig.xml $ddir/modoper_leafref_notif.xml"
+}}
+
+test data_operational_nested_notif_leafref {--operational data is referenced from nested-notification-leafref} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modoper-leafref"
+ ly_cmd "data -t notif -O $ddir/modoper_leafref_ds.xml $ddir/modoper_leafref_notif2.xml"
+}}
+
+test data_operational_nested_notif_parent_missing {--operational data are invalid due to missing parent node} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modoper-leafref"
+ set msg "klf='key_val']\" not found in the operational data"
+ ly_cmd_err "data -t notif -O $ddir/modconfig.xml $ddir/modoper_leafref_notif2.xml" $msg
+}}
+
+test data_operational_action_leafref {--operational data is referenced from action-leafref} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modoper-leafref"
+ ly_cmd "data -t rpc -O $ddir/modoper_leafref_ds.xml $ddir/modoper_leafref_action.xml"
+}}
+
+test data_operational_action_reply_leafref {--operational data is referenced from action-leafref output} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modoper-leafref"
+ ly_cmd "data -t reply -O $ddir/modoper_leafref_ds.xml $ddir/modoper_leafref_action_reply.xml"
+}}
+
+test data_operational_rpc_leafref {--operational data is referenced from rpc-leafref} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modoper-leafref"
+ ly_cmd "data -t rpc -O $ddir/modconfig.xml $ddir/modoper_leafref_rpc.xml"
+}}
+
+test data_operational_rpc_reply_leafref {--operational data is referenced from rpc-leafref output} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modoper-leafref"
+ ly_cmd "data -t reply -O $ddir/modconfig.xml $ddir/modoper_leafref_rpc_reply.xml"
+}}
+
+cleanupTests
diff --git a/tests/yanglint/interactive/data_present.test b/tests/yanglint/interactive/data_present.test
new file mode 100644
index 0000000..4bba596
--- /dev/null
+++ b/tests/yanglint/interactive/data_present.test
@@ -0,0 +1,25 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+
+set ddir "$::env(TESTS_DIR)/data"
+
+test data_present_via_mandatory {validation of mandatory-stmt will pass only with the --present} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modleaf modmandatory"
+ ly_cmd_err "data $ddir/modleaf.xml" "Mandatory node \"lft\" instance does not exist."
+ ly_cmd "data -e $ddir/modleaf.xml"
+}}
+
+test data_present_merge {validation with --present and --merge} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modleaf modmandatory moddefault"
+ ly_cmd_err "data -m $ddir/modleaf.xml $ddir/moddefault.xml" "Mandatory node \"lft\" instance does not exist."
+ ly_cmd "data -e -m $ddir/modleaf.xml $ddir/moddefault.xml"
+}}
+
+test data_present_merge_invalid {using --present and --merge but data are invalid} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modleaf modmandatory"
+ ly_cmd_err "data -e -m $ddir/modleaf.xml $ddir/modmandatory_invalid.xml" "Mandatory node \"lft\" instance does not exist."
+}}
+
+cleanupTests
diff --git a/tests/yanglint/interactive/data_type.test b/tests/yanglint/interactive/data_type.test
new file mode 100644
index 0000000..a442813
--- /dev/null
+++ b/tests/yanglint/interactive/data_type.test
@@ -0,0 +1,140 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+
+set ddir "$::env(TESTS_DIR)/data"
+
+test data_type_data {data --type data} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modconfig"
+ ly_cmd "data -t data $ddir/modconfig.xml"
+}}
+
+test data_type_config {data --type config} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modconfig"
+ ly_cmd_err "data -t config $ddir/modconfig.xml" "Unexpected data state node \"lff\""
+ ly_cmd "data -t config $ddir/modconfig2.xml"
+}}
+
+test data_type_get {data --type get} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modleafref"
+ ly_cmd_err "data -t data $ddir/modleafref2.xml" "Invalid leafref value"
+ ly_cmd "data -t get $ddir/modleafref2.xml"
+}}
+
+test data_type_getconfig_no_state {No state node for data --type getconfig} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modconfig"
+ ly_cmd_err "data -t getconfig $ddir/modconfig.xml" "Unexpected data state node \"lff\""
+ ly_cmd "data -t getconfig $ddir/modconfig2.xml"
+}}
+
+test data_type_getconfig_parse_only {No validation performed for data --type getconfig} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modleafref"
+ ly_cmd_err "data -t data $ddir/modleafref2.xml" "Invalid leafref value"
+ ly_cmd "data -t getconfig $ddir/modleafref2.xml"
+}}
+
+test data_type_edit_no_state {No state node for data --type edit} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modconfig"
+ ly_cmd_err "data -t edit $ddir/modconfig.xml" "Unexpected data state node \"lff\""
+ ly_cmd "data -t edit $ddir/modconfig2.xml"
+}}
+
+test data_type_edit_parse_only {No validation performed for data --type edit} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modleafref"
+ ly_cmd_err "data -t data $ddir/modleafref2.xml" "Invalid leafref value"
+ ly_cmd "data -t edit $ddir/modleafref2.xml"
+}}
+
+test data_type_rpc {Validation of rpc-statement by data --type rpc} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modrpc modleaf"
+ ly_cmd_err "data -t rpc $ddir/modleaf.xml" "Missing the operation node."
+ ly_cmd "data -t rpc $ddir/modrpc.xml"
+}}
+
+test data_type_rpc_nc {Validation of rpc-statement by data --type nc-rpc} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modrpc modleaf ietf-netconf"
+ ly_cmd_err "data -t nc-rpc $ddir/modleaf.xml" "Missing NETCONF <rpc> envelope"
+ ly_cmd "data -t nc-rpc $ddir/modrpc_nc.xml"
+}}
+
+test data_type_rpc_reply {Validation of rpc-reply by data --type reply} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modrpc modleaf"
+ ly_cmd_err "data -t rpc $ddir/modleaf.xml" "Missing the operation node."
+ ly_cmd_wrn "data -t reply -R $ddir/modrpc.xml $ddir/modrpc_reply.xml" "needed only for NETCONF"
+ ly_cmd "data -t reply $ddir/modrpc_reply.xml"
+}}
+
+test data_type_rpc_reply_nc {Validation of rpc-reply by data --type nc-reply} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modrpc modleaf"
+ ly_cmd_err "data -t nc-reply -R $ddir/modrpc_nc.xml $ddir/modleaf.xml" "Missing NETCONF <rpc-reply> envelope"
+ ly_cmd_err "data -t nc-reply $ddir/modrpc_reply_nc.xml" "Missing source RPC"
+ ly_cmd "data -t nc-reply -R $ddir/modrpc_nc.xml $ddir/modrpc_reply_nc.xml"
+}}
+
+test data_type_rpc_action {Validation of action-statement by data --type rpc} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modaction modleaf"
+ ly_cmd_err "data -t rpc $ddir/modleaf.xml" "Missing the operation node."
+ ly_cmd "data -t rpc -O $ddir/modaction_ds.xml $ddir/modaction.xml"
+}}
+
+test data_type_rpc_action_nc {Validation of action-statement by data --type nc-rpc} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modaction modleaf"
+ ly_cmd_err "data -t nc-rpc $ddir/modleaf.xml" "Missing NETCONF <rpc> envelope"
+ ly_cmd "data -t nc-rpc -O $ddir/modaction_ds.xml $ddir/modaction_nc.xml"
+}}
+
+test data_type_rpc_action_reply {Validation of action-reply by data --type reply} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modaction modleaf"
+ ly_cmd_err "data -t rpc $ddir/modleaf.xml" "Missing the operation node."
+ ly_cmd "data -t reply -O $ddir/modaction_ds.xml $ddir/modaction_reply.xml"
+}}
+
+test data_type_rpc_action_reply_nc {Validation of action-reply by data --type nc-reply} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modaction modleaf"
+ ly_cmd_err "data -t nc-reply -R $ddir/modaction_nc.xml $ddir/modleaf.xml" "Missing NETCONF <rpc-reply> envelope"
+ ly_cmd_err "data -t nc-reply $ddir/modaction_reply_nc.xml" "Missing source RPC"
+ ly_cmd_err "data -t nc-reply -R $ddir/modaction_nc.xml $ddir/modaction_reply_nc.xml" "operational parameter needed"
+ ly_cmd "data -t nc-reply -O $ddir/modaction_ds.xml -R $ddir/modaction_nc.xml $ddir/modaction_reply_nc.xml"
+}}
+
+test data_type_notif {Validation of notification-statement by data --type notif} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modnotif modleaf"
+ ly_cmd_err "data -t notif $ddir/modleaf.xml" "Missing the operation node."
+ ly_cmd "data -t notif $ddir/modnotif2.xml"
+}}
+
+test data_type_notif_nc {Validation of notification-statement by data --type nc-notif} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modnotif modleaf ietf-netconf"
+ ly_cmd_err "data -t nc-notif $ddir/modleaf.xml" "Missing NETCONF <notification> envelope"
+ ly_cmd "data -t nc-notif $ddir/modnotif2_nc.xml"
+}}
+
+test data_type_notif_nested {Validation of nested-notification-statement by data --type notif} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modnotif modleaf"
+ ly_cmd "data -t notif -O $ddir/modnotif_ds.xml $ddir/modnotif.xml"
+}}
+
+test data_type_notif_nested_nc {Validation of nested-notification-statement by data --type nc-notif} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modnotif modleaf ietf-netconf"
+ ly_cmd_err "data -t nc-notif $ddir/modleaf.xml" "Missing NETCONF <notification> envelope"
+ ly_cmd "data -t nc-notif -O $ddir/modnotif_ds.xml $ddir/modnotif_nc.xml"
+}}
+
+cleanupTests
diff --git a/tests/yanglint/interactive/data_xpath.test b/tests/yanglint/interactive/data_xpath.test
new file mode 100644
index 0000000..398cb9f
--- /dev/null
+++ b/tests/yanglint/interactive/data_xpath.test
@@ -0,0 +1,57 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+
+set data "$::env(TESTS_DIR)/data/moddatanodes.xml"
+
+test data_xpath_empty {--xpath to missing node} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load moddatanodes"
+ ly_cmd "data -x /moddatanodes:dnc/mis $data" "Empty"
+}}
+
+test data_xpath_leaf {--xpath to leaf node} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load moddatanodes"
+ ly_cmd "data -x /moddatanodes:dnc/lf $data" "leaf \"lf\" \\(value: \"x\"\\)"
+}}
+
+test data_xpath_leaflist {--xpath to leaf-list node} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load moddatanodes"
+ set r1 "leaf-list \"lfl\" \\(value: \"1\"\\)"
+ set r2 "leaf-list \"lfl\" \\(value: \"2\"\\)"
+ ly_cmd "data -x /moddatanodes:dnc/lfl $data" "$r1\r\n $r2"
+}}
+
+test data_xpath_list {--xpath to list} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load moddatanodes"
+ set r1 "list \"lt\" \\(\"kalf\": \"ka1\"; \"kblf\": \"kb1\";\\)"
+ set r2 "list \"lt\" \\(\"kalf\": \"ka2\"; \"kblf\": \"kb2\";\\)"
+ ly_cmd "data -x /moddatanodes:dnc/con/lt $data" "$r1\r\n $r2"
+}}
+
+test data_xpath_container {--xpath to container} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load moddatanodes"
+ ly_cmd "data -x /moddatanodes:dnc/con $data" "container \"con\""
+}}
+
+test data_xpath_wrong_path {--xpath to a non-existent node} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load moddatanodes"
+ ly_cmd_err "data -x /moddatanodes:dnc/wrng $data" "xpath failed"
+}}
+
+test data_xpath_err_format {--xpath cannot be combined with --format} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load moddatanodes"
+ ly_cmd_err "data -f xml -x /moddatanodes:dnc/lf $data" "option cannot be combined"
+}}
+
+test data_xpath_err_default {--xpath cannot be combined with --default} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load moddatanodes ietf-netconf-with-defaults"
+ ly_cmd_err "data -d all -x /moddatanodes:dnc/lf $data" "option cannot be combined"
+}}
+
+cleanupTests
diff --git a/tests/yanglint/interactive/debug.test b/tests/yanglint/interactive/debug.test
new file mode 100644
index 0000000..8a64c92
--- /dev/null
+++ b/tests/yanglint/interactive/debug.test
@@ -0,0 +1,33 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir $::env(YANG_MODULES_DIR)
+
+test debug_dict {Check debug message DICT} {
+-setup $ly_setup -cleanup $ly_cleanup -constraints {[yanglint_debug]} -body {
+ ly_cmd "verb debug"
+ ly_cmd "debug dict"
+ ly_cmd "load modleaf" "DICT"
+}}
+
+test debug_xpath {Check debug message XPATH} {
+-setup $ly_setup -cleanup $ly_cleanup -constraints {[yanglint_debug]} -body {
+ ly_cmd "verb debug"
+ ly_cmd "debug xpath"
+ ly_cmd "load modmust" "XPATH"
+}}
+
+test debug_dep_sets {Check debug message DEPSETS} {
+-setup $ly_setup -cleanup $ly_cleanup -constraints {[yanglint_debug]} -body {
+ ly_cmd "verb debug"
+ ly_cmd "debug dep-sets"
+ ly_cmd "load modleaf" "DEPSETS"
+}}
+
+test debug_depsets_xpath {Check debug message DEPSETS and XPATH} {
+-setup $ly_setup -cleanup $ly_cleanup -constraints {[yanglint_debug]} -body {
+ ly_cmd "verb debug"
+ ly_cmd "debug dep-sets xpath"
+ ly_cmd "load modmust" "DEPSETS.*XPATH"
+}}
+
+cleanupTests
diff --git a/tests/yanglint/interactive/extdata.test b/tests/yanglint/interactive/extdata.test
new file mode 100644
index 0000000..e253d1a
--- /dev/null
+++ b/tests/yanglint/interactive/extdata.test
@@ -0,0 +1,63 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir "$::env(YANG_MODULES_DIR)"
+set ddir "$::env(TESTS_DIR)/data"
+
+test extdata_set_clear {Set and clear extdata file} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "extdata" "No file set"
+ ly_cmd "extdata $ddir/modsm_ctx_ext.xml"
+ ly_cmd "extdata" "$ddir/modsm_ctx_ext.xml"
+ ly_cmd "extdata -c"
+ ly_cmd "extdata" "No file set"
+}}
+
+test extdata_clear_cmd {Clear extdata file by 'clear' command} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "extdata $ddir/modsm_ctx_ext.xml"
+ ly_cmd "clear"
+ ly_cmd "extdata" "No file set"
+}}
+
+test extdata_one_only {Only one file for extdata} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd_err "extdata $ddir/modsm_ctx_ext.xml $ddir/modsm_ctx_ext.xml" "Only one file must be entered"
+}}
+
+test extdata_schema_mount_tree {Print tree output of a model with Schema Mount} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "clear -y"
+ ly_cmd "searchpath $mdir"
+ ly_cmd "load modsm"
+ ly_cmd "extdata $ddir/modsm_ctx_ext.xml"
+ ly_cmd "print -f tree modsm" "--mp root.*--rw lfl/"
+}}
+
+test ext_data_schema_mount_tree_yanglibfile {Print tree output of a model with Schema Mount and --yang-library-file} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "clear -Y $ddir/modsm_ctx_main.xml"
+ ly_cmd "searchpath $mdir"
+ ly_cmd "load modsm"
+ ly_cmd "extdata $ddir/modsm_ctx_ext.xml"
+ ly_cmd "print -f tree modsm" "--mp root.*--rw lfl/.*--rw msa:alf?"
+}}
+
+test ext_data_schema_mount_xml {Validating and printing mounted data} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "clear -y"
+ ly_cmd "searchpath $mdir"
+ ly_cmd "load modsm"
+ ly_cmd "extdata $ddir/modsm_ctx_ext.xml"
+ ly_cmd "data -f xml -t config $ddir/modsm.xml" "</lfl>"
+}}
+
+test ext_data_schema_mount_xml_yanglibfile {Validating and printing mounted data with --yang-library-file} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "clear -Y $ddir/modsm_ctx_main.xml"
+ ly_cmd "searchpath $mdir"
+ ly_cmd "load modsm"
+ ly_cmd "extdata $ddir/modsm_ctx_ext.xml"
+ ly_cmd "data -f xml -t config $ddir/modsm2.xml" "</lfl>.*</alf>"
+}}
+
+cleanupTests
diff --git a/tests/yanglint/interactive/feature.test b/tests/yanglint/interactive/feature.test
new file mode 100644
index 0000000..84bfa8e
--- /dev/null
+++ b/tests/yanglint/interactive/feature.test
@@ -0,0 +1,37 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+
+test feature_all_default {Default output of feature --all} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "feature -a" "yang:\r\n\t(none)\r\n\r\nietf-yang-schema-mount:\r\n\t(none)\r\n" -ex
+}}
+
+test feature_all_add_module {Add module with only one feature and call feature --all} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load --feature modfeature:ftr1 modfeature"
+ ly_cmd "feature -a" "modfeature:\r\n\tftr1 \\(on\\)\r\n\tftr2 \\(off\\)"
+}}
+
+test feature_all_on {Add module with all enabled features and call feature --all} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load --feature modfeature:* modfeature"
+ ly_cmd "feature -a" "modfeature:\r\n\tftr1 \\(on\\)\r\n\tftr2 \\(on\\)"
+}}
+
+test feature_one_module {Show features for one module} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load ietf-ip"
+ ly_cmd "feature -f ietf-ip" " -F ietf-ip:ipv4-non-contiguous-netmasks,ipv6-privacy-autoconf" -ex
+}}
+
+test feature_more_modules {Show a mix of modules with and without features} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+
+ set features " -F modfeature:ftr1,ftr2\
+-F modleaf:\
+-F ietf-ip:ipv4-non-contiguous-netmasks,ipv6-privacy-autoconf"
+
+ ly_cmd "load ietf-ip modleaf modfeature"
+ ly_cmd "feature -f modfeature modleaf ietf-ip" $features -ex
+}}
+
+cleanupTests
diff --git a/tests/yanglint/interactive/list.test b/tests/yanglint/interactive/list.test
new file mode 100644
index 0000000..ab59a32
--- /dev/null
+++ b/tests/yanglint/interactive/list.test
@@ -0,0 +1,34 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+namespace import uti::regex_xml_elements uti::regex_json_pairs
+
+set modules {ietf-yang-library ietf-inet-types}
+
+test list_basic {basic test} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "list" "ietf-yang-types"
+}}
+
+test list_format_xml {list --format xml} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "clear -y"
+ ly_cmd "list -f xml" [regex_xml_elements $modules "name"]
+}}
+
+test list_format_json {list --format json} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "clear -y"
+ ly_cmd "list -f json" [regex_json_pairs $modules "name"]
+}}
+
+test list_ietf_yang_library {Error due to missing ietf-yang-library} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd_err "list -f xml" "Module \"ietf-yang-library\" is not implemented."
+}}
+
+test list_bad_format {Error due to bad format} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "clear -y"
+ ly_cmd_err "list -f csv" "Unknown output format csv"
+}}
+
+cleanupTests
diff --git a/tests/yanglint/interactive/load.test b/tests/yanglint/interactive/load.test
new file mode 100644
index 0000000..a95d044
--- /dev/null
+++ b/tests/yanglint/interactive/load.test
@@ -0,0 +1,45 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+
+test load_basic {} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modleafref"
+ ly_cmd "list" "I modleafref\r.*I modleaf"
+}}
+
+test load_with_feature {Load module with feature} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load --feature modfeature:ftr2 modfeature"
+ ly_cmd "feature -a" "modfeature:\r\n\tftr1 \\(off\\)\r\n\tftr2 \\(on\\)"
+}}
+
+test load_make_implemented_once {load --make-implemented} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_ignore "load modmust"
+ ly_cmd "list" "I modmust\r.*i modleaf"
+ ly_cmd "clear"
+ ly_cmd "searchpath $::env(YANG_MODULES_DIR)"
+ ly_cmd "load -i modmust"
+ ly_cmd "list" "I modmust\r.*I modleaf"
+}}
+
+test load_make_implemented_twice {load -i -i} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modimp-type"
+ ly_cmd "list" "I modimp-type\r.*i modtypedef"
+ ly_cmd "clear"
+ ly_cmd "searchpath $::env(YANG_MODULES_DIR)"
+ ly_cmd "load -i -i modimp-type"
+ ly_cmd "list" "I modimp-type\r.*I modtypedef"
+}}
+
+test load_extended_leafref_enabled {Valid module with --extended-leafref option} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load -X modextleafref"
+}}
+
+test load_extended_leafref_disabled {Expected error if --extended-leafref is not set} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd_err "load modextleafref" "Unexpected XPath token \"FunctionName\""
+}}
+
+cleanupTests
diff --git a/tests/yanglint/interactive/ly.tcl b/tests/yanglint/interactive/ly.tcl
new file mode 100644
index 0000000..4c56be4
--- /dev/null
+++ b/tests/yanglint/interactive/ly.tcl
@@ -0,0 +1,81 @@
+# @brief The main source of functions and variables for testing yanglint in the interactive mode.
+
+# For testing yanglint.
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/common.tcl" : "../common.tcl"}]
+# For testing any interactive tool.
+source "$::env(TESTS_DIR)/../tool_i.tcl"
+
+# The script continues by defining variables and functions specific to the interactive yanglint tool.
+
+# set the timeout to 5 seconds
+set timeout 5
+# prompt of yanglint
+set prompt "> "
+# turn off dialog between expect and yanglint
+log_user 0
+# setting some large terminal width
+stty columns 720
+
+# default setup for every unit test
+variable ly_setup {
+ spawn $TUT
+ ly_skip_warnings
+ # Searchpath is set, so modules can be loaded via the 'load' command.
+ ly_cmd "searchpath $::env(YANG_MODULES_DIR)"
+}
+
+# default cleanup for every unit test
+variable ly_cleanup {
+ ly_exit
+}
+
+# Skip no dir and/or no history warnings and prompt.
+proc ly_skip_warnings {} {
+ global prompt
+ expect -re "(YANGLINT.*)*$prompt" {}
+}
+
+# Send command 'cmd' to the process, expect error header and then check output string by 'pattern'.
+# Parameter cmd is a string of arguments.
+# Parameter pattern is a regex. It must not contain a prompt.
+proc ly_cmd_err {cmd pattern} {
+ global prompt
+
+ send -- "${cmd}\r"
+ expect -- "${cmd}\r\n"
+
+ expect {
+ -re "YANGLINT\\\[E\\\]: .*${pattern}.*\r\n${prompt}$" {}
+ -re "libyang\\\[\[0-9]+\\\]: .*${pattern}.*\r\n${prompt}$" {}
+ -re "\r\n${prompt}$" {
+ error "unexpected output:\n$expect_out(buffer)"
+ }
+ }
+}
+
+# Send command 'cmd' to the process, expect warning header and then check output string by 'pattern'.
+# Parameter cmd is a string of arguments.
+# Parameter pattern is a regex. It must not contain a prompt.
+proc ly_cmd_wrn {cmd pattern} {
+ ly_cmd_header $cmd "YANGLINT\\\[W\\\]:" $pattern
+}
+
+# Send 'exit' and wait for eof.
+proc ly_exit {} {
+ send "exit\r"
+ expect eof
+}
+
+# Check if yanglint is configured as DEBUG.
+# Return 1 on success.
+proc yanglint_debug {} {
+ global TUT
+ # Call non-interactive yanglint with --help.
+ set output [exec -- $TUT "-h"]
+ # Find option --debug.
+ if { [regexp -- "--debug=GROUPS" $output] } {
+ return 1
+ } else {
+ return 0
+ }
+}
diff --git a/tests/yanglint/interactive/modcwd.yang b/tests/yanglint/interactive/modcwd.yang
new file mode 100644
index 0000000..db33e73
--- /dev/null
+++ b/tests/yanglint/interactive/modcwd.yang
@@ -0,0 +1,4 @@
+module modcwd {
+ namespace "urn:yanglint:modcwd";
+ prefix mc;
+}
diff --git a/tests/yanglint/interactive/print.test b/tests/yanglint/interactive/print.test
new file mode 100644
index 0000000..8b9d740
--- /dev/null
+++ b/tests/yanglint/interactive/print.test
@@ -0,0 +1,77 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+
+set ipv6_path "/ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address"
+
+test print_yang {} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modleaf"
+ ly_cmd "print -f yang modleaf" "leaf lfl"
+}}
+
+test print_yang_submodule {Print submodule in yang format} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modinclude"
+ ly_cmd "print -f yang modsub" "submodule modsub"
+}}
+
+test print_yin {} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modleaf"
+ ly_cmd "print -f yin modleaf" "<leaf name=\"lfl\">"
+}}
+
+test print_yin_submodule {Print submodule in yin format} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modinclude"
+ ly_cmd "print -f yin modsub" "<submodule name=\"modsub\""
+}}
+
+test print_info {} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modleaf"
+ ly_cmd "print -f info modleaf" "status current"
+}}
+
+test print_info_path {Print subtree in info format} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load ietf-ip"
+ ly_cmd "print -f info -P $ipv6_path" "^list address .* leaf prefix-length"
+}}
+
+test print_info_path_single_node {Print node in info format} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load ietf-ip"
+ ly_cmd "print -f info -q -P $ipv6_path" "^list address .* IPv6 addresses on the interface.\";\r\n\}$"
+}}
+
+test print_tree {} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modleaf"
+ ly_cmd "print -f tree modleaf" "\\+--rw lfl"
+}}
+
+test print_tree_submodule {Print submodule in tree format} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load modinclude"
+ ly_cmd "print -f tree modsub" "submodule: modsub"
+}}
+
+test print_tree_path {Print subtree in tree format} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load ietf-ip"
+ ly_cmd "print -f tree -P $ipv6_path" "\\+--rw address.*\\+--rw prefix-length"
+}}
+
+test print_tree_path_single_node {Print node in tree format} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load ietf-ip"
+ ly_cmd "print -f tree -q -P $ipv6_path" "\\+--rw address\\* \\\[ip\\\]$"
+}}
+
+test print_tree_path_single_node_line_length {Print node in the tree format and limit row size} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "load ietf-ip"
+ ly_cmd "print -f tree -L 20 -q -P $ipv6_path" "\\+--rw address\\*\r\n *\\\[ip\\\]$"
+}}
+
+cleanupTests
diff --git a/tests/yanglint/interactive/searchpath.test b/tests/yanglint/interactive/searchpath.test
new file mode 100644
index 0000000..3bd6796
--- /dev/null
+++ b/tests/yanglint/interactive/searchpath.test
@@ -0,0 +1,24 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir $::env(YANG_MODULES_DIR)
+
+variable ly_setup {
+ spawn $TUT
+ ly_skip_warnings
+}
+
+test searchpath_basic {} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "searchpath $mdir"
+ ly_cmd "searchpath" "$mdir"
+ ly_cmd "load modleaf"
+}}
+
+test searchpath_clear {searchpath --clear} {
+-setup $ly_setup -cleanup $ly_cleanup -body {
+ ly_cmd "searchpath $mdir"
+ ly_cmd "searchpath --clear"
+ ly_cmd_err "load modleaf" "Data model \"modleaf\" not found in local searchdirs"
+}}
+
+cleanupTests
diff --git a/tests/yanglint/modules/ietf-interfaces.yang b/tests/yanglint/modules/ietf-interfaces.yang
new file mode 100644
index 0000000..ad64425
--- /dev/null
+++ b/tests/yanglint/modules/ietf-interfaces.yang
@@ -0,0 +1,725 @@
+module ietf-interfaces {
+
+ namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces";
+ prefix if;
+
+ import ietf-yang-types {
+ prefix yang;
+ }
+
+ organization
+ "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+ contact
+ "WG Web: <http://tools.ietf.org/wg/netmod/>
+ WG List: <mailto:netmod@ietf.org>
+
+ WG Chair: Thomas Nadeau
+ <mailto:tnadeau@lucidvision.com>
+
+ WG Chair: Juergen Schoenwaelder
+ <mailto:j.schoenwaelder@jacobs-university.de>
+
+ Editor: Martin Bjorklund
+ <mailto:mbj@tail-f.com>";
+
+ description
+ "This module contains a collection of YANG definitions for
+ managing network interfaces.
+
+ Copyright (c) 2014 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, is permitted pursuant to, and subject
+ to the license terms contained in, the Simplified BSD License
+ set forth in Section 4.c of the IETF Trust's Legal Provisions
+ Relating to IETF Documents
+ (http://trustee.ietf.org/license-info).
+
+ This version of this YANG module is part of RFC 7223; see
+ the RFC itself for full legal notices.";
+
+ revision 2014-05-08 {
+ description
+ "Initial revision.";
+ reference
+ "RFC 7223: A YANG Data Model for Interface Management";
+ }
+
+ /*
+ * Typedefs
+ */
+
+ typedef interface-ref {
+ type leafref {
+ path "/if:interfaces/if:interface/if:name";
+ }
+ description
+ "This type is used by data models that need to reference
+ configured interfaces.";
+ }
+
+ typedef interface-state-ref {
+ type leafref {
+ path "/if:interfaces-state/if:interface/if:name";
+ }
+ description
+ "This type is used by data models that need to reference
+ the operationally present interfaces.";
+ }
+
+ /*
+ * Identities
+ */
+
+ identity interface-type {
+ description
+ "Base identity from which specific interface types are
+ derived.";
+ }
+
+ /*
+ * Features
+ */
+
+ feature arbitrary-names {
+ description
+ "This feature indicates that the device allows user-controlled
+ interfaces to be named arbitrarily.";
+ }
+ feature pre-provisioning {
+ description
+ "This feature indicates that the device supports
+ pre-provisioning of interface configuration, i.e., it is
+ possible to configure an interface whose physical interface
+ hardware is not present on the device.";
+ }
+
+ feature if-mib {
+ description
+ "This feature indicates that the device implements
+ the IF-MIB.";
+ reference
+ "RFC 2863: The Interfaces Group MIB";
+ }
+
+ /*
+ * Configuration data nodes
+ */
+
+ container interfaces {
+ description
+ "Interface configuration parameters.";
+
+ list interface {
+ key "name";
+
+ description
+ "The list of configured interfaces on the device.
+
+ The operational state of an interface is available in the
+ /interfaces-state/interface list. If the configuration of a
+ system-controlled interface cannot be used by the system
+ (e.g., the interface hardware present does not match the
+ interface type), then the configuration is not applied to
+ the system-controlled interface shown in the
+ /interfaces-state/interface list. If the configuration
+ of a user-controlled interface cannot be used by the system,
+ the configured interface is not instantiated in the
+ /interfaces-state/interface list.";
+
+ leaf name {
+ type string;
+ description
+ "The name of the interface.
+
+ A device MAY restrict the allowed values for this leaf,
+ possibly depending on the type of the interface.
+ For system-controlled interfaces, this leaf is the
+ device-specific name of the interface. The 'config false'
+ list /interfaces-state/interface contains the currently
+ existing interfaces on the device.
+
+ If a client tries to create configuration for a
+ system-controlled interface that is not present in the
+ /interfaces-state/interface list, the server MAY reject
+ the request if the implementation does not support
+ pre-provisioning of interfaces or if the name refers to
+ an interface that can never exist in the system. A
+ NETCONF server MUST reply with an rpc-error with the
+ error-tag 'invalid-value' in this case.
+
+ If the device supports pre-provisioning of interface
+ configuration, the 'pre-provisioning' feature is
+ advertised.
+
+ If the device allows arbitrarily named user-controlled
+ interfaces, the 'arbitrary-names' feature is advertised.
+
+ When a configured user-controlled interface is created by
+ the system, it is instantiated with the same name in the
+ /interface-state/interface list.";
+ }
+
+ leaf description {
+ type string;
+ description
+ "A textual description of the interface.
+
+ A server implementation MAY map this leaf to the ifAlias
+ MIB object. Such an implementation needs to use some
+ mechanism to handle the differences in size and characters
+ allowed between this leaf and ifAlias. The definition of
+ such a mechanism is outside the scope of this document.
+
+ Since ifAlias is defined to be stored in non-volatile
+ storage, the MIB implementation MUST map ifAlias to the
+ value of 'description' in the persistently stored
+ datastore.
+
+ Specifically, if the device supports ':startup', when
+ ifAlias is read the device MUST return the value of
+ 'description' in the 'startup' datastore, and when it is
+ written, it MUST be written to the 'running' and 'startup'
+ datastores. Note that it is up to the implementation to
+
+ decide whether to modify this single leaf in 'startup' or
+ perform an implicit copy-config from 'running' to
+ 'startup'.
+
+ If the device does not support ':startup', ifAlias MUST
+ be mapped to the 'description' leaf in the 'running'
+ datastore.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifAlias";
+ }
+
+ leaf type {
+ type identityref {
+ base interface-type;
+ }
+ mandatory true;
+ description
+ "The type of the interface.
+
+ When an interface entry is created, a server MAY
+ initialize the type leaf with a valid value, e.g., if it
+ is possible to derive the type from the name of the
+ interface.
+
+ If a client tries to set the type of an interface to a
+ value that can never be used by the system, e.g., if the
+ type is not supported or if the type does not match the
+ name of the interface, the server MUST reject the request.
+ A NETCONF server MUST reply with an rpc-error with the
+ error-tag 'invalid-value' in this case.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifType";
+ }
+
+ leaf enabled {
+ type boolean;
+ default "true";
+ description
+ "This leaf contains the configured, desired state of the
+ interface.
+
+ Systems that implement the IF-MIB use the value of this
+ leaf in the 'running' datastore to set
+ IF-MIB.ifAdminStatus to 'up' or 'down' after an ifEntry
+ has been initialized, as described in RFC 2863.
+
+
+
+ Changes in this leaf in the 'running' datastore are
+ reflected in ifAdminStatus, but if ifAdminStatus is
+ changed over SNMP, this leaf is not affected.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifAdminStatus";
+ }
+
+ leaf link-up-down-trap-enable {
+ if-feature if-mib;
+ type enumeration {
+ enum enabled {
+ value 1;
+ }
+ enum disabled {
+ value 2;
+ }
+ }
+ description
+ "Controls whether linkUp/linkDown SNMP notifications
+ should be generated for this interface.
+
+ If this node is not configured, the value 'enabled' is
+ operationally used by the server for interfaces that do
+ not operate on top of any other interface (i.e., there are
+ no 'lower-layer-if' entries), and 'disabled' otherwise.";
+ reference
+ "RFC 2863: The Interfaces Group MIB -
+ ifLinkUpDownTrapEnable";
+ }
+ }
+ }
+
+ /*
+ * Operational state data nodes
+ */
+
+ container interfaces-state {
+ config false;
+ description
+ "Data nodes for the operational state of interfaces.";
+
+ list interface {
+ key "name";
+
+
+
+
+
+ description
+ "The list of interfaces on the device.
+
+ System-controlled interfaces created by the system are
+ always present in this list, whether they are configured or
+ not.";
+
+ leaf name {
+ type string;
+ description
+ "The name of the interface.
+
+ A server implementation MAY map this leaf to the ifName
+ MIB object. Such an implementation needs to use some
+ mechanism to handle the differences in size and characters
+ allowed between this leaf and ifName. The definition of
+ such a mechanism is outside the scope of this document.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifName";
+ }
+
+ leaf type {
+ type identityref {
+ base interface-type;
+ }
+ mandatory true;
+ description
+ "The type of the interface.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifType";
+ }
+
+ leaf admin-status {
+ if-feature if-mib;
+ type enumeration {
+ enum up {
+ value 1;
+ description
+ "Ready to pass packets.";
+ }
+ enum down {
+ value 2;
+ description
+ "Not ready to pass packets and not in some test mode.";
+ }
+
+
+
+ enum testing {
+ value 3;
+ description
+ "In some test mode.";
+ }
+ }
+ mandatory true;
+ description
+ "The desired state of the interface.
+
+ This leaf has the same read semantics as ifAdminStatus.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifAdminStatus";
+ }
+
+ leaf oper-status {
+ type enumeration {
+ enum up {
+ value 1;
+ description
+ "Ready to pass packets.";
+ }
+ enum down {
+ value 2;
+ description
+ "The interface does not pass any packets.";
+ }
+ enum testing {
+ value 3;
+ description
+ "In some test mode. No operational packets can
+ be passed.";
+ }
+ enum unknown {
+ value 4;
+ description
+ "Status cannot be determined for some reason.";
+ }
+ enum dormant {
+ value 5;
+ description
+ "Waiting for some external event.";
+ }
+ enum not-present {
+ value 6;
+ description
+ "Some component (typically hardware) is missing.";
+ }
+ enum lower-layer-down {
+ value 7;
+ description
+ "Down due to state of lower-layer interface(s).";
+ }
+ }
+ mandatory true;
+ description
+ "The current operational state of the interface.
+
+ This leaf has the same semantics as ifOperStatus.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifOperStatus";
+ }
+
+ leaf last-change {
+ type yang:date-and-time;
+ description
+ "The time the interface entered its current operational
+ state. If the current state was entered prior to the
+ last re-initialization of the local network management
+ subsystem, then this node is not present.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifLastChange";
+ }
+
+ leaf if-index {
+ if-feature if-mib;
+ type int32 {
+ range "1..2147483647";
+ }
+ mandatory true;
+ description
+ "The ifIndex value for the ifEntry represented by this
+ interface.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifIndex";
+ }
+
+ leaf phys-address {
+ type yang:phys-address;
+ description
+ "The interface's address at its protocol sub-layer. For
+ example, for an 802.x interface, this object normally
+ contains a Media Access Control (MAC) address. The
+ interface's media-specific modules must define the bit
+
+
+ and byte ordering and the format of the value of this
+ object. For interfaces that do not have such an address
+ (e.g., a serial line), this node is not present.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifPhysAddress";
+ }
+
+ leaf-list higher-layer-if {
+ type interface-state-ref;
+ description
+ "A list of references to interfaces layered on top of this
+ interface.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifStackTable";
+ }
+
+ leaf-list lower-layer-if {
+ type interface-state-ref;
+ description
+ "A list of references to interfaces layered underneath this
+ interface.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifStackTable";
+ }
+
+ leaf speed {
+ type yang:gauge64;
+ units "bits/second";
+ description
+ "An estimate of the interface's current bandwidth in bits
+ per second. For interfaces that do not vary in
+ bandwidth or for those where no accurate estimation can
+ be made, this node should contain the nominal bandwidth.
+ For interfaces that have no concept of bandwidth, this
+ node is not present.";
+ reference
+ "RFC 2863: The Interfaces Group MIB -
+ ifSpeed, ifHighSpeed";
+ }
+
+
+
+
+
+
+
+
+
+ container statistics {
+ description
+ "A collection of interface-related statistics objects.";
+
+ leaf discontinuity-time {
+ type yang:date-and-time;
+ mandatory true;
+ description
+ "The time on the most recent occasion at which any one or
+ more of this interface's counters suffered a
+ discontinuity. If no such discontinuities have occurred
+ since the last re-initialization of the local management
+ subsystem, then this node contains the time the local
+ management subsystem re-initialized itself.";
+ }
+
+ leaf in-octets {
+ type yang:counter64;
+ description
+ "The total number of octets received on the interface,
+ including framing characters.
+
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system, and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifHCInOctets";
+ }
+
+ leaf in-unicast-pkts {
+ type yang:counter64;
+ description
+ "The number of packets, delivered by this sub-layer to a
+ higher (sub-)layer, that were not addressed to a
+ multicast or broadcast address at this sub-layer.
+
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system, and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts";
+ }
+
+
+
+
+ leaf in-broadcast-pkts {
+ type yang:counter64;
+ description
+ "The number of packets, delivered by this sub-layer to a
+ higher (sub-)layer, that were addressed to a broadcast
+ address at this sub-layer.
+
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system, and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB -
+ ifHCInBroadcastPkts";
+ }
+
+ leaf in-multicast-pkts {
+ type yang:counter64;
+ description
+ "The number of packets, delivered by this sub-layer to a
+ higher (sub-)layer, that were addressed to a multicast
+ address at this sub-layer. For a MAC-layer protocol,
+ this includes both Group and Functional addresses.
+
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system, and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB -
+ ifHCInMulticastPkts";
+ }
+
+ leaf in-discards {
+ type yang:counter32;
+ description
+ "The number of inbound packets that were chosen to be
+ discarded even though no errors had been detected to
+ prevent their being deliverable to a higher-layer
+ protocol. One possible reason for discarding such a
+ packet could be to free up buffer space.
+
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system, and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+
+
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifInDiscards";
+ }
+
+ leaf in-errors {
+ type yang:counter32;
+ description
+ "For packet-oriented interfaces, the number of inbound
+ packets that contained errors preventing them from being
+ deliverable to a higher-layer protocol. For character-
+ oriented or fixed-length interfaces, the number of
+ inbound transmission units that contained errors
+ preventing them from being deliverable to a higher-layer
+ protocol.
+
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system, and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifInErrors";
+ }
+
+ leaf in-unknown-protos {
+ type yang:counter32;
+ description
+ "For packet-oriented interfaces, the number of packets
+ received via the interface that were discarded because
+ of an unknown or unsupported protocol. For
+ character-oriented or fixed-length interfaces that
+ support protocol multiplexing, the number of
+ transmission units received via the interface that were
+ discarded because of an unknown or unsupported protocol.
+ For any interface that does not support protocol
+ multiplexing, this counter is not present.
+
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system, and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos";
+ }
+
+
+
+
+
+ leaf out-octets {
+ type yang:counter64;
+ description
+ "The total number of octets transmitted out of the
+ interface, including framing characters.
+
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system, and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifHCOutOctets";
+ }
+
+ leaf out-unicast-pkts {
+ type yang:counter64;
+ description
+ "The total number of packets that higher-level protocols
+ requested be transmitted, and that were not addressed
+ to a multicast or broadcast address at this sub-layer,
+ including those that were discarded or not sent.
+
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system, and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts";
+ }
+
+ leaf out-broadcast-pkts {
+ type yang:counter64;
+ description
+ "The total number of packets that higher-level protocols
+ requested be transmitted, and that were addressed to a
+ broadcast address at this sub-layer, including those
+ that were discarded or not sent.
+
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system, and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB -
+ ifHCOutBroadcastPkts";
+ }
+
+
+ leaf out-multicast-pkts {
+ type yang:counter64;
+ description
+ "The total number of packets that higher-level protocols
+ requested be transmitted, and that were addressed to a
+ multicast address at this sub-layer, including those
+ that were discarded or not sent. For a MAC-layer
+ protocol, this includes both Group and Functional
+ addresses.
+
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system, and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB -
+ ifHCOutMulticastPkts";
+ }
+
+ leaf out-discards {
+ type yang:counter32;
+ description
+ "The number of outbound packets that were chosen to be
+ discarded even though no errors had been detected to
+ prevent their being transmitted. One possible reason
+ for discarding such a packet could be to free up buffer
+ space.
+
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system, and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifOutDiscards";
+ }
+
+ leaf out-errors {
+ type yang:counter32;
+ description
+ "For packet-oriented interfaces, the number of outbound
+ packets that could not be transmitted because of errors.
+ For character-oriented or fixed-length interfaces, the
+ number of outbound transmission units that could not be
+ transmitted because of errors.
+
+
+
+
+ Discontinuities in the value of this counter can occur
+ at re-initialization of the management system, and at
+ other times as indicated by the value of
+ 'discontinuity-time'.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifOutErrors";
+ }
+ }
+ }
+ }
+}
diff --git a/tests/yanglint/modules/ietf-ip.yang b/tests/yanglint/modules/ietf-ip.yang
new file mode 100644
index 0000000..1499120
--- /dev/null
+++ b/tests/yanglint/modules/ietf-ip.yang
@@ -0,0 +1,758 @@
+module ietf-ip {
+
+ namespace "urn:ietf:params:xml:ns:yang:ietf-ip";
+ prefix ip;
+
+ import ietf-interfaces {
+ prefix if;
+ }
+ import ietf-inet-types {
+ prefix inet;
+ }
+ import ietf-yang-types {
+ prefix yang;
+ }
+
+ organization
+ "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+ contact
+ "WG Web: <http://tools.ietf.org/wg/netmod/>
+ WG List: <mailto:netmod@ietf.org>
+
+ WG Chair: Thomas Nadeau
+ <mailto:tnadeau@lucidvision.com>
+
+ WG Chair: Juergen Schoenwaelder
+ <mailto:j.schoenwaelder@jacobs-university.de>
+
+ Editor: Martin Bjorklund
+ <mailto:mbj@tail-f.com>";
+
+
+
+
+
+
+
+
+
+
+ description
+ "This module contains a collection of YANG definitions for
+ configuring IP implementations.
+
+ Copyright (c) 2014 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, is permitted pursuant to, and subject
+ to the license terms contained in, the Simplified BSD License
+ set forth in Section 4.c of the IETF Trust's Legal Provisions
+ Relating to IETF Documents
+ (http://trustee.ietf.org/license-info).
+
+ This version of this YANG module is part of RFC 7277; see
+ the RFC itself for full legal notices.";
+
+ revision 2014-06-16 {
+ description
+ "Initial revision.";
+ reference
+ "RFC 7277: A YANG Data Model for IP Management";
+ }
+
+ /*
+
+ * Features
+ */
+
+ feature ipv4-non-contiguous-netmasks {
+ description
+ "Indicates support for configuring non-contiguous
+ subnet masks.";
+ }
+
+ feature ipv6-privacy-autoconf {
+ description
+ "Indicates support for Privacy Extensions for Stateless Address
+ Autoconfiguration in IPv6.";
+ reference
+ "RFC 4941: Privacy Extensions for Stateless Address
+ Autoconfiguration in IPv6";
+ }
+
+
+
+
+
+ /*
+ * Typedefs
+ */
+
+ typedef ip-address-origin {
+ type enumeration {
+ enum other {
+ description
+ "None of the following.";
+ }
+ enum static {
+ description
+ "Indicates that the address has been statically
+ configured - for example, using NETCONF or a Command Line
+ Interface.";
+ }
+ enum dhcp {
+ description
+ "Indicates an address that has been assigned to this
+ system by a DHCP server.";
+ }
+ enum link-layer {
+ description
+ "Indicates an address created by IPv6 stateless
+ autoconfiguration that embeds a link-layer address in its
+ interface identifier.";
+ }
+ enum random {
+ description
+ "Indicates an address chosen by the system at
+
+ random, e.g., an IPv4 address within 169.254/16, an
+ RFC 4941 temporary address, or an RFC 7217 semantically
+ opaque address.";
+ reference
+ "RFC 4941: Privacy Extensions for Stateless Address
+ Autoconfiguration in IPv6
+ RFC 7217: A Method for Generating Semantically Opaque
+ Interface Identifiers with IPv6 Stateless
+ Address Autoconfiguration (SLAAC)";
+ }
+ }
+ description
+ "The origin of an address.";
+ }
+
+
+
+ typedef neighbor-origin {
+ type enumeration {
+ enum other {
+ description
+ "None of the following.";
+ }
+ enum static {
+ description
+ "Indicates that the mapping has been statically
+ configured - for example, using NETCONF or a Command Line
+ Interface.";
+ }
+ enum dynamic {
+ description
+ "Indicates that the mapping has been dynamically resolved
+ using, e.g., IPv4 ARP or the IPv6 Neighbor Discovery
+ protocol.";
+ }
+ }
+ description
+ "The origin of a neighbor entry.";
+ }
+
+ /*
+ * Configuration data nodes
+ */
+
+ augment "/if:interfaces/if:interface" {
+ description
+ "Parameters for configuring IP on interfaces.
+
+ If an interface is not capable of running IP, the server
+ must not allow the client to configure these parameters.";
+
+ container ipv4 {
+ presence
+ "Enables IPv4 unless the 'enabled' leaf
+ (which defaults to 'true') is set to 'false'";
+ description
+ "Parameters for the IPv4 address family.";
+
+
+
+
+
+
+
+
+ leaf enabled {
+ type boolean;
+ default true;
+ description
+ "Controls whether IPv4 is enabled or disabled on this
+ interface. When IPv4 is enabled, this interface is
+ connected to an IPv4 stack, and the interface can send
+ and receive IPv4 packets.";
+ }
+ leaf forwarding {
+ type boolean;
+ default false;
+ description
+ "Controls IPv4 packet forwarding of datagrams received by,
+ but not addressed to, this interface. IPv4 routers
+ forward datagrams. IPv4 hosts do not (except those
+ source-routed via the host).";
+ }
+ leaf mtu {
+ type uint16 {
+ range "68..max";
+ }
+ units octets;
+ description
+ "The size, in octets, of the largest IPv4 packet that the
+ interface will send and receive.
+
+ The server may restrict the allowed values for this leaf,
+ depending on the interface's type.
+
+ If this leaf is not configured, the operationally used MTU
+ depends on the interface's type.";
+ reference
+ "RFC 791: Internet Protocol";
+ }
+ list address {
+ key "ip";
+ description
+ "The list of configured IPv4 addresses on the interface.";
+
+ leaf ip {
+ type inet:ipv4-address-no-zone;
+ description
+ "The IPv4 address on the interface.";
+ }
+
+
+
+ choice subnet {
+ mandatory true;
+ description
+ "The subnet can be specified as a prefix-length, or,
+ if the server supports non-contiguous netmasks, as
+ a netmask.";
+ leaf prefix-length {
+ type uint8 {
+ range "0..32";
+ }
+ description
+ "The length of the subnet prefix.";
+ }
+ leaf netmask {
+ if-feature ipv4-non-contiguous-netmasks;
+ type yang:dotted-quad;
+ description
+ "The subnet specified as a netmask.";
+ }
+ }
+ }
+ list neighbor {
+ key "ip";
+ description
+ "A list of mappings from IPv4 addresses to
+ link-layer addresses.
+
+ Entries in this list are used as static entries in the
+ ARP Cache.";
+ reference
+ "RFC 826: An Ethernet Address Resolution Protocol";
+
+ leaf ip {
+ type inet:ipv4-address-no-zone;
+ description
+ "The IPv4 address of the neighbor node.";
+ }
+ leaf link-layer-address {
+ type yang:phys-address;
+ mandatory true;
+ description
+ "The link-layer address of the neighbor node.";
+ }
+ }
+
+ }
+
+
+ container ipv6 {
+ presence
+ "Enables IPv6 unless the 'enabled' leaf
+ (which defaults to 'true') is set to 'false'";
+ description
+ "Parameters for the IPv6 address family.";
+
+ leaf enabled {
+ type boolean;
+ default true;
+ description
+ "Controls whether IPv6 is enabled or disabled on this
+ interface. When IPv6 is enabled, this interface is
+ connected to an IPv6 stack, and the interface can send
+ and receive IPv6 packets.";
+ }
+ leaf forwarding {
+ type boolean;
+ default false;
+ description
+ "Controls IPv6 packet forwarding of datagrams received by,
+ but not addressed to, this interface. IPv6 routers
+ forward datagrams. IPv6 hosts do not (except those
+ source-routed via the host).";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)
+ Section 6.2.1, IsRouter";
+ }
+ leaf mtu {
+ type uint32 {
+ range "1280..max";
+ }
+ units octets;
+ description
+ "The size, in octets, of the largest IPv6 packet that the
+ interface will send and receive.
+
+ The server may restrict the allowed values for this leaf,
+ depending on the interface's type.
+
+ If this leaf is not configured, the operationally used MTU
+ depends on the interface's type.";
+ reference
+ "RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
+ Section 5";
+ }
+
+
+ list address {
+ key "ip";
+ description
+ "The list of configured IPv6 addresses on the interface.";
+
+ leaf ip {
+ type inet:ipv6-address-no-zone;
+ description
+ "The IPv6 address on the interface.";
+ }
+ leaf prefix-length {
+ type uint8 {
+ range "0..128";
+ }
+ mandatory true;
+ description
+ "The length of the subnet prefix.";
+ }
+ }
+ list neighbor {
+ key "ip";
+ description
+ "A list of mappings from IPv6 addresses to
+ link-layer addresses.
+
+ Entries in this list are used as static entries in the
+ Neighbor Cache.";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)";
+
+ leaf ip {
+ type inet:ipv6-address-no-zone;
+ description
+ "The IPv6 address of the neighbor node.";
+ }
+ leaf link-layer-address {
+ type yang:phys-address;
+ mandatory true;
+ description
+ "The link-layer address of the neighbor node.";
+ }
+ }
+
+
+
+
+
+
+ leaf dup-addr-detect-transmits {
+ type uint32;
+ default 1;
+ description
+ "The number of consecutive Neighbor Solicitation messages
+ sent while performing Duplicate Address Detection on a
+ tentative address. A value of zero indicates that
+ Duplicate Address Detection is not performed on
+ tentative addresses. A value of one indicates a single
+ transmission with no follow-up retransmissions.";
+ reference
+ "RFC 4862: IPv6 Stateless Address Autoconfiguration";
+ }
+ container autoconf {
+ description
+ "Parameters to control the autoconfiguration of IPv6
+ addresses, as described in RFC 4862.";
+ reference
+ "RFC 4862: IPv6 Stateless Address Autoconfiguration";
+
+ leaf create-global-addresses {
+ type boolean;
+ default true;
+ description
+ "If enabled, the host creates global addresses as
+ described in RFC 4862.";
+ reference
+ "RFC 4862: IPv6 Stateless Address Autoconfiguration
+ Section 5.5";
+ }
+ leaf create-temporary-addresses {
+ if-feature ipv6-privacy-autoconf;
+ type boolean;
+ default false;
+ description
+ "If enabled, the host creates temporary addresses as
+ described in RFC 4941.";
+ reference
+ "RFC 4941: Privacy Extensions for Stateless Address
+ Autoconfiguration in IPv6";
+ }
+
+
+
+
+
+
+
+ leaf temporary-valid-lifetime {
+ if-feature ipv6-privacy-autoconf;
+ type uint32;
+ units "seconds";
+ default 604800;
+ description
+ "The time period during which the temporary address
+ is valid.";
+ reference
+ "RFC 4941: Privacy Extensions for Stateless Address
+ Autoconfiguration in IPv6
+ - TEMP_VALID_LIFETIME";
+ }
+ leaf temporary-preferred-lifetime {
+ if-feature ipv6-privacy-autoconf;
+ type uint32;
+ units "seconds";
+ default 86400;
+ description
+ "The time period during which the temporary address is
+ preferred.";
+ reference
+ "RFC 4941: Privacy Extensions for Stateless Address
+ Autoconfiguration in IPv6
+ - TEMP_PREFERRED_LIFETIME";
+ }
+ }
+ }
+ }
+
+ /*
+ * Operational state data nodes
+ */
+
+ augment "/if:interfaces-state/if:interface" {
+ description
+ "Data nodes for the operational state of IP on interfaces.";
+
+ container ipv4 {
+ presence "Present if IPv4 is enabled on this interface";
+ config false;
+ description
+ "Interface-specific parameters for the IPv4 address family.";
+
+
+
+
+
+ leaf forwarding {
+ type boolean;
+ description
+ "Indicates whether IPv4 packet forwarding is enabled or
+ disabled on this interface.";
+ }
+ leaf mtu {
+ type uint16 {
+ range "68..max";
+ }
+ units octets;
+ description
+ "The size, in octets, of the largest IPv4 packet that the
+ interface will send and receive.";
+ reference
+ "RFC 791: Internet Protocol";
+ }
+ list address {
+ key "ip";
+ description
+ "The list of IPv4 addresses on the interface.";
+
+ leaf ip {
+ type inet:ipv4-address-no-zone;
+ description
+ "The IPv4 address on the interface.";
+ }
+ choice subnet {
+ description
+ "The subnet can be specified as a prefix-length, or,
+ if the server supports non-contiguous netmasks, as
+ a netmask.";
+ leaf prefix-length {
+ type uint8 {
+ range "0..32";
+ }
+ description
+ "The length of the subnet prefix.";
+ }
+ leaf netmask {
+ if-feature ipv4-non-contiguous-netmasks;
+ type yang:dotted-quad;
+ description
+ "The subnet specified as a netmask.";
+ }
+ }
+
+
+ leaf origin {
+ type ip-address-origin;
+ description
+ "The origin of this address.";
+ }
+ }
+ list neighbor {
+ key "ip";
+ description
+ "A list of mappings from IPv4 addresses to
+ link-layer addresses.
+
+ This list represents the ARP Cache.";
+ reference
+ "RFC 826: An Ethernet Address Resolution Protocol";
+
+ leaf ip {
+ type inet:ipv4-address-no-zone;
+ description
+ "The IPv4 address of the neighbor node.";
+ }
+ leaf link-layer-address {
+ type yang:phys-address;
+ description
+ "The link-layer address of the neighbor node.";
+ }
+ leaf origin {
+ type neighbor-origin;
+ description
+ "The origin of this neighbor entry.";
+ }
+ }
+
+ }
+
+ container ipv6 {
+ presence "Present if IPv6 is enabled on this interface";
+ config false;
+ description
+ "Parameters for the IPv6 address family.";
+
+
+
+
+
+
+
+
+ leaf forwarding {
+ type boolean;
+ default false;
+ description
+ "Indicates whether IPv6 packet forwarding is enabled or
+ disabled on this interface.";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)
+ Section 6.2.1, IsRouter";
+ }
+ leaf mtu {
+ type uint32 {
+ range "1280..max";
+ }
+ units octets;
+ description
+ "The size, in octets, of the largest IPv6 packet that the
+ interface will send and receive.";
+ reference
+ "RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
+ Section 5";
+ }
+ list address {
+ key "ip";
+ description
+ "The list of IPv6 addresses on the interface.";
+
+ leaf ip {
+ type inet:ipv6-address-no-zone;
+ description
+ "The IPv6 address on the interface.";
+ }
+ leaf prefix-length {
+ type uint8 {
+ range "0..128";
+ }
+ mandatory true;
+ description
+ "The length of the subnet prefix.";
+ }
+ leaf origin {
+ type ip-address-origin;
+ description
+ "The origin of this address.";
+ }
+
+
+
+ leaf status {
+ type enumeration {
+ enum preferred {
+ description
+ "This is a valid address that can appear as the
+ destination or source address of a packet.";
+ }
+ enum deprecated {
+ description
+ "This is a valid but deprecated address that should
+ no longer be used as a source address in new
+ communications, but packets addressed to such an
+ address are processed as expected.";
+ }
+ enum invalid {
+ description
+ "This isn't a valid address, and it shouldn't appear
+ as the destination or source address of a packet.";
+ }
+ enum inaccessible {
+ description
+ "The address is not accessible because the interface
+ to which this address is assigned is not
+ operational.";
+ }
+ enum unknown {
+ description
+ "The status cannot be determined for some reason.";
+ }
+ enum tentative {
+ description
+ "The uniqueness of the address on the link is being
+ verified. Addresses in this state should not be
+ used for general communication and should only be
+ used to determine the uniqueness of the address.";
+ }
+ enum duplicate {
+ description
+ "The address has been determined to be non-unique on
+ the link and so must not be used.";
+ }
+
+
+
+
+
+
+
+ enum optimistic {
+ description
+ "The address is available for use, subject to
+ restrictions, while its uniqueness on a link is
+ being verified.";
+ }
+ }
+ description
+ "The status of an address. Most of the states correspond
+ to states from the IPv6 Stateless Address
+ Autoconfiguration protocol.";
+ reference
+ "RFC 4293: Management Information Base for the
+ Internet Protocol (IP)
+ - IpAddressStatusTC
+ RFC 4862: IPv6 Stateless Address Autoconfiguration";
+ }
+ }
+ list neighbor {
+ key "ip";
+ description
+ "A list of mappings from IPv6 addresses to
+ link-layer addresses.
+
+ This list represents the Neighbor Cache.";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)";
+
+ leaf ip {
+ type inet:ipv6-address-no-zone;
+ description
+ "The IPv6 address of the neighbor node.";
+ }
+ leaf link-layer-address {
+ type yang:phys-address;
+ description
+ "The link-layer address of the neighbor node.";
+ }
+ leaf origin {
+ type neighbor-origin;
+ description
+ "The origin of this neighbor entry.";
+ }
+ leaf is-router {
+ type empty;
+ description
+ "Indicates that the neighbor node acts as a router.";
+ }
+ leaf state {
+ type enumeration {
+ enum incomplete {
+ description
+ "Address resolution is in progress, and the link-layer
+ address of the neighbor has not yet been
+ determined.";
+ }
+ enum reachable {
+ description
+ "Roughly speaking, the neighbor is known to have been
+ reachable recently (within tens of seconds ago).";
+ }
+ enum stale {
+ description
+ "The neighbor is no longer known to be reachable, but
+ until traffic is sent to the neighbor no attempt
+ should be made to verify its reachability.";
+ }
+ enum delay {
+ description
+ "The neighbor is no longer known to be reachable, and
+ traffic has recently been sent to the neighbor.
+ Rather than probe the neighbor immediately, however,
+ delay sending probes for a short while in order to
+ give upper-layer protocols a chance to provide
+ reachability confirmation.";
+ }
+ enum probe {
+ description
+ "The neighbor is no longer known to be reachable, and
+ unicast Neighbor Solicitation probes are being sent
+ to verify reachability.";
+ }
+ }
+ description
+ "The Neighbor Unreachability Detection state of this
+ entry.";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)
+ Section 7.3.2";
+ }
+ }
+ }
+ }
+}
diff --git a/tests/yanglint/modules/ietf-netconf-acm.yang b/tests/yanglint/modules/ietf-netconf-acm.yang
new file mode 100644
index 0000000..d372fa0
--- /dev/null
+++ b/tests/yanglint/modules/ietf-netconf-acm.yang
@@ -0,0 +1,411 @@
+module ietf-netconf-acm {
+ namespace "urn:ietf:params:xml:ns:yang:ietf-netconf-acm";
+ prefix nacm;
+
+ import ietf-yang-types {
+ prefix yang;
+ }
+
+ organization
+ "IETF NETCONF (Network Configuration) Working Group";
+ contact
+ "WG Web: <http://tools.ietf.org/wg/netconf/>
+ WG List: <mailto:netconf@ietf.org>
+
+ WG Chair: Mehmet Ersue
+ <mailto:mehmet.ersue@nsn.com>
+
+ WG Chair: Bert Wijnen
+ <mailto:bertietf@bwijnen.net>
+
+ Editor: Andy Bierman
+ <mailto:andy@yumaworks.com>
+
+ Editor: Martin Bjorklund
+ <mailto:mbj@tail-f.com>";
+ description
+ "NETCONF Access Control Model.
+
+ Copyright (c) 2012 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, is permitted pursuant to, and subject
+ to the license terms contained in, the Simplified BSD
+ License set forth in Section 4.c of the IETF Trust's
+ Legal Provisions Relating to IETF Documents
+ (http://trustee.ietf.org/license-info).
+
+ This version of this YANG module is part of RFC 6536; see
+ the RFC itself for full legal notices.";
+
+ revision 2012-02-22 {
+ description
+ "Initial version";
+ reference
+ "RFC 6536: Network Configuration Protocol (NETCONF)
+ Access Control Model";
+ }
+
+ extension default-deny-write {
+ description
+ "Used to indicate that the data model node
+ represents a sensitive security system parameter.
+
+ If present, and the NACM module is enabled (i.e.,
+ /nacm/enable-nacm object equals 'true'), the NETCONF server
+ will only allow the designated 'recovery session' to have
+ write access to the node. An explicit access control rule is
+ required for all other users.
+
+ The 'default-deny-write' extension MAY appear within a data
+ definition statement. It is ignored otherwise.";
+ }
+
+ extension default-deny-all {
+ description
+ "Used to indicate that the data model node
+ controls a very sensitive security system parameter.
+
+ If present, and the NACM module is enabled (i.e.,
+ /nacm/enable-nacm object equals 'true'), the NETCONF server
+ will only allow the designated 'recovery session' to have
+ read, write, or execute access to the node. An explicit
+ access control rule is required for all other users.
+
+ The 'default-deny-all' extension MAY appear within a data
+ definition statement, 'rpc' statement, or 'notification'
+ statement. It is ignored otherwise.";
+ }
+
+ typedef user-name-type {
+ type string {
+ length "1..max";
+ }
+ description
+ "General Purpose Username string.";
+ }
+
+ typedef matchall-string-type {
+ type string {
+ pattern "\\*";
+ }
+ description
+ "The string containing a single asterisk '*' is used
+ to conceptually represent all possible values
+ for the particular leaf using this data type.";
+ }
+
+ typedef access-operations-type {
+ type bits {
+ bit create {
+ description
+ "Any protocol operation that creates a
+ new data node.";
+ }
+ bit read {
+ description
+ "Any protocol operation or notification that
+ returns the value of a data node.";
+ }
+ bit update {
+ description
+ "Any protocol operation that alters an existing
+ data node.";
+ }
+ bit delete {
+ description
+ "Any protocol operation that removes a data node.";
+ }
+ bit exec {
+ description
+ "Execution access to the specified protocol operation.";
+ }
+ }
+ description
+ "NETCONF Access Operation.";
+ }
+
+ typedef group-name-type {
+ type string {
+ length "1..max";
+ pattern "[^\\*].*";
+ }
+ description
+ "Name of administrative group to which
+ users can be assigned.";
+ }
+
+ typedef action-type {
+ type enumeration {
+ enum "permit" {
+ description
+ "Requested action is permitted.";
+ }
+ enum "deny" {
+ description
+ "Requested action is denied.";
+ }
+ }
+ description
+ "Action taken by the server when a particular
+ rule matches.";
+ }
+
+ typedef node-instance-identifier {
+ type yang:xpath1.0;
+ description
+ "Path expression used to represent a special
+ data node instance identifier string.
+
+ A node-instance-identifier value is an
+ unrestricted YANG instance-identifier expression.
+ All the same rules as an instance-identifier apply
+ except predicates for keys are optional. If a key
+ predicate is missing, then the node-instance-identifier
+ represents all possible server instances for that key.
+
+ This XPath expression is evaluated in the following context:
+
+ o The set of namespace declarations are those in scope on
+ the leaf element where this type is used.
+
+ o The set of variable bindings contains one variable,
+ 'USER', which contains the name of the user of the current
+ session.
+
+ o The function library is the core function library, but
+ note that due to the syntax restrictions of an
+ instance-identifier, no functions are allowed.
+
+ o The context node is the root node in the data tree.";
+ }
+
+ container nacm {
+ nacm:default-deny-all;
+ description
+ "Parameters for NETCONF Access Control Model.";
+ leaf enable-nacm {
+ type boolean;
+ default "true";
+ description
+ "Enables or disables all NETCONF access control
+ enforcement. If 'true', then enforcement
+ is enabled. If 'false', then enforcement
+ is disabled.";
+ }
+ leaf read-default {
+ type action-type;
+ default "permit";
+ description
+ "Controls whether read access is granted if
+ no appropriate rule is found for a
+ particular read request.";
+ }
+ leaf write-default {
+ type action-type;
+ default "deny";
+ description
+ "Controls whether create, update, or delete access
+ is granted if no appropriate rule is found for a
+ particular write request.";
+ }
+ leaf exec-default {
+ type action-type;
+ default "permit";
+ description
+ "Controls whether exec access is granted if no appropriate
+ rule is found for a particular protocol operation request.";
+ }
+ leaf enable-external-groups {
+ type boolean;
+ default "true";
+ description
+ "Controls whether the server uses the groups reported by the
+ NETCONF transport layer when it assigns the user to a set of
+ NACM groups. If this leaf has the value 'false', any group
+ names reported by the transport layer are ignored by the
+ server.";
+ }
+ leaf denied-operations {
+ type yang:zero-based-counter32;
+ config false;
+ mandatory true;
+ description
+ "Number of times since the server last restarted that a
+ protocol operation request was denied.";
+ }
+ leaf denied-data-writes {
+ type yang:zero-based-counter32;
+ config false;
+ mandatory true;
+ description
+ "Number of times since the server last restarted that a
+ protocol operation request to alter
+ a configuration datastore was denied.";
+ }
+ leaf denied-notifications {
+ type yang:zero-based-counter32;
+ config false;
+ mandatory true;
+ description
+ "Number of times since the server last restarted that
+ a notification was dropped for a subscription because
+ access to the event type was denied.";
+ }
+ container groups {
+ description
+ "NETCONF Access Control Groups.";
+ list group {
+ key "name";
+ description
+ "One NACM Group Entry. This list will only contain
+ configured entries, not any entries learned from
+ any transport protocols.";
+ leaf name {
+ type group-name-type;
+ description
+ "Group name associated with this entry.";
+ }
+ leaf-list user-name {
+ type user-name-type;
+ description
+ "Each entry identifies the username of
+ a member of the group associated with
+ this entry.";
+ }
+ }
+ }
+ list rule-list {
+ key "name";
+ ordered-by user;
+ description
+ "An ordered collection of access control rules.";
+ leaf name {
+ type string {
+ length "1..max";
+ }
+ description
+ "Arbitrary name assigned to the rule-list.";
+ }
+ leaf-list group {
+ type union {
+ type matchall-string-type;
+ type group-name-type;
+ }
+ description
+ "List of administrative groups that will be
+ assigned the associated access rights
+ defined by the 'rule' list.
+
+ The string '*' indicates that all groups apply to the
+ entry.";
+ }
+ list rule {
+ key "name";
+ ordered-by user;
+ description
+ "One access control rule.
+
+ Rules are processed in user-defined order until a match is
+ found. A rule matches if 'module-name', 'rule-type', and
+ 'access-operations' match the request. If a rule
+ matches, the 'action' leaf determines if access is granted
+ or not.";
+ leaf name {
+ type string {
+ length "1..max";
+ }
+ description
+ "Arbitrary name assigned to the rule.";
+ }
+ leaf module-name {
+ type union {
+ type matchall-string-type;
+ type string;
+ }
+ default "*";
+ description
+ "Name of the module associated with this rule.
+
+ This leaf matches if it has the value '*' or if the
+ object being accessed is defined in the module with the
+ specified module name.";
+ }
+ choice rule-type {
+ description
+ "This choice matches if all leafs present in the rule
+ match the request. If no leafs are present, the
+ choice matches all requests.";
+ case protocol-operation {
+ leaf rpc-name {
+ type union {
+ type matchall-string-type;
+ type string;
+ }
+ description
+ "This leaf matches if it has the value '*' or if
+ its value equals the requested protocol operation
+ name.";
+ }
+ }
+ case notification {
+ leaf notification-name {
+ type union {
+ type matchall-string-type;
+ type string;
+ }
+ description
+ "This leaf matches if it has the value '*' or if its
+ value equals the requested notification name.";
+ }
+ }
+ case data-node {
+ leaf path {
+ type node-instance-identifier;
+ mandatory true;
+ description
+ "Data Node Instance Identifier associated with the
+ data node controlled by this rule.
+
+ Configuration data or state data instance
+ identifiers start with a top-level data node. A
+ complete instance identifier is required for this
+ type of path value.
+
+ The special value '/' refers to all possible
+ datastore contents.";
+ }
+ }
+ }
+ leaf access-operations {
+ type union {
+ type matchall-string-type;
+ type access-operations-type;
+ }
+ default "*";
+ description
+ "Access operations associated with this rule.
+
+ This leaf matches if it has the value '*' or if the
+ bit corresponding to the requested operation is set.";
+ }
+ leaf action {
+ type action-type;
+ mandatory true;
+ description
+ "The access control action associated with the
+ rule. If a rule is determined to match a
+ particular request, then this object is used
+ to determine whether to permit or deny the
+ request.";
+ }
+ leaf comment {
+ type string;
+ description
+ "A textual description of the access rule.";
+ }
+ }
+ }
+ }
+}
diff --git a/tests/yanglint/modules/ietf-netconf-with-defaults@2011-06-01.yang b/tests/yanglint/modules/ietf-netconf-with-defaults@2011-06-01.yang
new file mode 100644
index 0000000..e19d2b3
--- /dev/null
+++ b/tests/yanglint/modules/ietf-netconf-with-defaults@2011-06-01.yang
@@ -0,0 +1,140 @@
+module ietf-netconf-with-defaults {
+
+ namespace "urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults";
+
+ prefix ncwd;
+
+ import ietf-netconf { prefix nc; }
+
+ organization
+ "IETF NETCONF (Network Configuration Protocol) Working Group";
+
+ contact
+ "WG Web: <http://tools.ietf.org/wg/netconf/>
+
+ WG List: <netconf@ietf.org>
+
+ WG Chair: Bert Wijnen
+ <bertietf@bwijnen.net>
+
+ WG Chair: Mehmet Ersue
+ <mehmet.ersue@nsn.com>
+
+ Editor: Andy Bierman
+ <andy.bierman@brocade.com>
+
+ Editor: Balazs Lengyel
+ <balazs.lengyel@ericsson.com>";
+
+ description
+ "This module defines an extension to the NETCONF protocol
+ that allows the NETCONF client to control how default
+ values are handled by the server in particular NETCONF
+ operations.
+
+ Copyright (c) 2011 IETF Trust and the persons identified as
+ the document authors. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, is permitted pursuant to, and subject
+ to the license terms contained in, the Simplified BSD License
+ set forth in Section 4.c of the IETF Trust's Legal Provisions
+ Relating to IETF Documents
+ (http://trustee.ietf.org/license-info).
+
+ This version of this YANG module is part of RFC 6243; see
+ the RFC itself for full legal notices.";
+
+ revision 2011-06-01 {
+ description
+ "Initial version.";
+ reference
+ "RFC 6243: With-defaults Capability for NETCONF";
+ }
+
+ typedef with-defaults-mode {
+ description
+ "Possible modes to report default data.";
+ reference
+ "RFC 6243; Section 3.";
+ type enumeration {
+ enum report-all {
+ description
+ "All default data is reported.";
+ reference
+ "RFC 6243; Section 3.1";
+ }
+ enum report-all-tagged {
+ description
+ "All default data is reported.
+ Any nodes considered to be default data
+ will contain a 'default' XML attribute,
+ set to 'true' or '1'.";
+ reference
+ "RFC 6243; Section 3.4";
+ }
+ enum trim {
+ description
+ "Values are not reported if they contain the default.";
+ reference
+ "RFC 6243; Section 3.2";
+ }
+ enum explicit {
+ description
+ "Report values that contain the definition of
+ explicitly set data.";
+ reference
+ "RFC 6243; Section 3.3";
+ }
+ }
+ }
+
+ grouping with-defaults-parameters {
+ description
+ "Contains the <with-defaults> parameter for control
+ of defaults in NETCONF retrieval operations.";
+
+ leaf with-defaults {
+ description
+ "The explicit defaults processing mode requested.";
+ reference
+ "RFC 6243; Section 4.5.1";
+
+ type with-defaults-mode;
+ }
+ }
+
+ // extending the get-config operation
+ augment /nc:get-config/nc:input {
+ description
+ "Adds the <with-defaults> parameter to the
+ input of the NETCONF <get-config> operation.";
+ reference
+ "RFC 6243; Section 4.5.1";
+
+ uses with-defaults-parameters;
+ }
+
+ // extending the get operation
+ augment /nc:get/nc:input {
+ description
+ "Adds the <with-defaults> parameter to
+ the input of the NETCONF <get> operation.";
+ reference
+ "RFC 6243; Section 4.5.1";
+
+ uses with-defaults-parameters;
+ }
+
+ // extending the copy-config operation
+ augment /nc:copy-config/nc:input {
+ description
+ "Adds the <with-defaults> parameter to
+ the input of the NETCONF <copy-config> operation.";
+ reference
+ "RFC 6243; Section 4.5.1";
+
+ uses with-defaults-parameters;
+ }
+
+}
diff --git a/tests/yanglint/modules/ietf-netconf@2011-06-01.yang b/tests/yanglint/modules/ietf-netconf@2011-06-01.yang
new file mode 100644
index 0000000..3053db2
--- /dev/null
+++ b/tests/yanglint/modules/ietf-netconf@2011-06-01.yang
@@ -0,0 +1,934 @@
+module ietf-netconf {
+
+ // the namespace for NETCONF XML definitions is unchanged
+ // from RFC 4741, which this document replaces
+ namespace "urn:ietf:params:xml:ns:netconf:base:1.0";
+
+ prefix nc;
+
+ import ietf-inet-types {
+ prefix inet;
+ }
+
+ import ietf-netconf-acm { prefix nacm; }
+
+ organization
+ "IETF NETCONF (Network Configuration) Working Group";
+
+ contact
+ "WG Web: <http://tools.ietf.org/wg/netconf/>
+ WG List: <netconf@ietf.org>
+
+ WG Chair: Bert Wijnen
+ <bertietf@bwijnen.net>
+
+ WG Chair: Mehmet Ersue
+ <mehmet.ersue@nsn.com>
+
+ Editor: Martin Bjorklund
+ <mbj@tail-f.com>
+
+ Editor: Juergen Schoenwaelder
+ <j.schoenwaelder@jacobs-university.de>
+
+ Editor: Andy Bierman
+ <andy.bierman@brocade.com>";
+ description
+ "NETCONF Protocol Data Types and Protocol Operations.
+
+ Copyright (c) 2011 IETF Trust and the persons identified as
+ the document authors. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, is permitted pursuant to, and subject
+ to the license terms contained in, the Simplified BSD License
+ set forth in Section 4.c of the IETF Trust's Legal Provisions
+ Relating to IETF Documents
+ (http://trustee.ietf.org/license-info).
+
+ This version of this YANG module is part of RFC 6241; see
+ the RFC itself for full legal notices.";
+
+ revision 2011-06-01 {
+ description
+ "Initial revision;
+ 2013-09-29: Updated to include NACM attributes,
+ as specified in RFC 6536: sec 3.2.5 and 3.2.8";
+ reference
+ "RFC 6241: Network Configuration Protocol";
+ }
+
+ extension get-filter-element-attributes {
+ description
+ "If this extension is present within an 'anyxml'
+ statement named 'filter', which must be conceptually
+ defined within the RPC input section for the <get>
+ and <get-config> protocol operations, then the
+ following unqualified XML attribute is supported
+ within the <filter> element, within a <get> or
+ <get-config> protocol operation:
+
+ type : optional attribute with allowed
+ value strings 'subtree' and 'xpath'.
+ If missing, the default value is 'subtree'.
+
+ If the 'xpath' feature is supported, then the
+ following unqualified XML attribute is
+ also supported:
+
+ select: optional attribute containing a
+ string representing an XPath expression.
+ The 'type' attribute must be equal to 'xpath'
+ if this attribute is present.";
+ }
+
+ // NETCONF capabilities defined as features
+ feature writable-running {
+ description
+ "NETCONF :writable-running capability;
+ If the server advertises the :writable-running
+ capability for a session, then this feature must
+ also be enabled for that session. Otherwise,
+ this feature must not be enabled.";
+ reference "RFC 6241, Section 8.2";
+ }
+
+ feature candidate {
+ description
+ "NETCONF :candidate capability;
+ If the server advertises the :candidate
+ capability for a session, then this feature must
+ also be enabled for that session. Otherwise,
+ this feature must not be enabled.";
+ reference "RFC 6241, Section 8.3";
+ }
+
+ feature confirmed-commit {
+ if-feature candidate;
+ description
+ "NETCONF :confirmed-commit:1.1 capability;
+ If the server advertises the :confirmed-commit:1.1
+ capability for a session, then this feature must
+ also be enabled for that session. Otherwise,
+ this feature must not be enabled.";
+
+ reference "RFC 6241, Section 8.4";
+ }
+
+ feature rollback-on-error {
+ description
+ "NETCONF :rollback-on-error capability;
+ If the server advertises the :rollback-on-error
+ capability for a session, then this feature must
+ also be enabled for that session. Otherwise,
+ this feature must not be enabled.";
+ reference "RFC 6241, Section 8.5";
+ }
+
+ feature validate {
+ description
+ "NETCONF :validate:1.1 capability;
+ If the server advertises the :validate:1.1
+ capability for a session, then this feature must
+ also be enabled for that session. Otherwise,
+ this feature must not be enabled.";
+ reference "RFC 6241, Section 8.6";
+ }
+
+ feature startup {
+ description
+ "NETCONF :startup capability;
+ If the server advertises the :startup
+ capability for a session, then this feature must
+ also be enabled for that session. Otherwise,
+ this feature must not be enabled.";
+ reference "RFC 6241, Section 8.7";
+ }
+
+ feature url {
+ description
+ "NETCONF :url capability;
+ If the server advertises the :url
+ capability for a session, then this feature must
+ also be enabled for that session. Otherwise,
+ this feature must not be enabled.";
+ reference "RFC 6241, Section 8.8";
+ }
+
+ feature xpath {
+ description
+ "NETCONF :xpath capability;
+ If the server advertises the :xpath
+ capability for a session, then this feature must
+ also be enabled for that session. Otherwise,
+ this feature must not be enabled.";
+ reference "RFC 6241, Section 8.9";
+ }
+
+ // NETCONF Simple Types
+
+ typedef session-id-type {
+ type uint32 {
+ range "1..max";
+ }
+ description
+ "NETCONF Session Id";
+ }
+
+ typedef session-id-or-zero-type {
+ type uint32;
+ description
+ "NETCONF Session Id or Zero to indicate none";
+ }
+ typedef error-tag-type {
+ type enumeration {
+ enum in-use {
+ description
+ "The request requires a resource that
+ already is in use.";
+ }
+ enum invalid-value {
+ description
+ "The request specifies an unacceptable value for one
+ or more parameters.";
+ }
+ enum too-big {
+ description
+ "The request or response (that would be generated) is
+ too large for the implementation to handle.";
+ }
+ enum missing-attribute {
+ description
+ "An expected attribute is missing.";
+ }
+ enum bad-attribute {
+ description
+ "An attribute value is not correct; e.g., wrong type,
+ out of range, pattern mismatch.";
+ }
+ enum unknown-attribute {
+ description
+ "An unexpected attribute is present.";
+ }
+ enum missing-element {
+ description
+ "An expected element is missing.";
+ }
+ enum bad-element {
+ description
+ "An element value is not correct; e.g., wrong type,
+ out of range, pattern mismatch.";
+ }
+ enum unknown-element {
+ description
+ "An unexpected element is present.";
+ }
+ enum unknown-namespace {
+ description
+ "An unexpected namespace is present.";
+ }
+ enum access-denied {
+ description
+ "Access to the requested protocol operation or
+ data model is denied because authorization failed.";
+ }
+ enum lock-denied {
+ description
+ "Access to the requested lock is denied because the
+ lock is currently held by another entity.";
+ }
+ enum resource-denied {
+ description
+ "Request could not be completed because of
+ insufficient resources.";
+ }
+ enum rollback-failed {
+ description
+ "Request to roll back some configuration change (via
+ rollback-on-error or <discard-changes> operations)
+ was not completed for some reason.";
+
+ }
+ enum data-exists {
+ description
+ "Request could not be completed because the relevant
+ data model content already exists. For example,
+ a 'create' operation was attempted on data that
+ already exists.";
+ }
+ enum data-missing {
+ description
+ "Request could not be completed because the relevant
+ data model content does not exist. For example,
+ a 'delete' operation was attempted on
+ data that does not exist.";
+ }
+ enum operation-not-supported {
+ description
+ "Request could not be completed because the requested
+ operation is not supported by this implementation.";
+ }
+ enum operation-failed {
+ description
+ "Request could not be completed because the requested
+ operation failed for some reason not covered by
+ any other error condition.";
+ }
+ enum partial-operation {
+ description
+ "This error-tag is obsolete, and SHOULD NOT be sent
+ by servers conforming to this document.";
+ }
+ enum malformed-message {
+ description
+ "A message could not be handled because it failed to
+ be parsed correctly. For example, the message is not
+ well-formed XML or it uses an invalid character set.";
+ }
+ }
+ description "NETCONF Error Tag";
+ reference "RFC 6241, Appendix A";
+ }
+
+ typedef error-severity-type {
+ type enumeration {
+ enum error {
+ description "Error severity";
+ }
+ enum warning {
+ description "Warning severity";
+ }
+ }
+ description "NETCONF Error Severity";
+ reference "RFC 6241, Section 4.3";
+ }
+
+ typedef edit-operation-type {
+ type enumeration {
+ enum merge {
+ description
+ "The configuration data identified by the
+ element containing this attribute is merged
+ with the configuration at the corresponding
+ level in the configuration datastore identified
+ by the target parameter.";
+ }
+ enum replace {
+ description
+ "The configuration data identified by the element
+ containing this attribute replaces any related
+ configuration in the configuration datastore
+ identified by the target parameter. If no such
+ configuration data exists in the configuration
+ datastore, it is created. Unlike a
+ <copy-config> operation, which replaces the
+ entire target configuration, only the configuration
+ actually present in the config parameter is affected.";
+ }
+ enum create {
+ description
+ "The configuration data identified by the element
+ containing this attribute is added to the
+ configuration if and only if the configuration
+ data does not already exist in the configuration
+ datastore. If the configuration data exists, an
+ <rpc-error> element is returned with an
+ <error-tag> value of 'data-exists'.";
+ }
+ enum delete {
+ description
+ "The configuration data identified by the element
+ containing this attribute is deleted from the
+ configuration if and only if the configuration
+ data currently exists in the configuration
+ datastore. If the configuration data does not
+ exist, an <rpc-error> element is returned with
+ an <error-tag> value of 'data-missing'.";
+ }
+ enum remove {
+ description
+ "The configuration data identified by the element
+ containing this attribute is deleted from the
+ configuration if the configuration
+ data currently exists in the configuration
+ datastore. If the configuration data does not
+ exist, the 'remove' operation is silently ignored
+ by the server.";
+ }
+ }
+ default "merge";
+ description "NETCONF 'operation' attribute values";
+ reference "RFC 6241, Section 7.2";
+ }
+
+ // NETCONF Standard Protocol Operations
+
+ rpc get-config {
+ description
+ "Retrieve all or part of a specified configuration.";
+
+ reference "RFC 6241, Section 7.1";
+
+ input {
+ container source {
+ description
+ "Particular configuration to retrieve.";
+
+ choice config-source {
+ mandatory true;
+ description
+ "The configuration to retrieve.";
+ leaf candidate {
+ if-feature candidate;
+ type empty;
+ description
+ "The candidate configuration is the config source.";
+ }
+ leaf running {
+ type empty;
+ description
+ "The running configuration is the config source.";
+ }
+ leaf startup {
+ if-feature startup;
+ type empty;
+ description
+ "The startup configuration is the config source.
+ This is optional-to-implement on the server because
+ not all servers will support filtering for this
+ datastore.";
+ }
+ }
+ }
+
+ anyxml filter {
+ description
+ "Subtree or XPath filter to use.";
+ nc:get-filter-element-attributes;
+ }
+ }
+
+ output {
+ anyxml data {
+ description
+ "Copy of the source datastore subset that matched
+ the filter criteria (if any). An empty data container
+ indicates that the request did not produce any results.";
+ }
+ }
+ }
+
+ rpc edit-config {
+ description
+ "The <edit-config> operation loads all or part of a specified
+ configuration to the specified target configuration.";
+
+ reference "RFC 6241, Section 7.2";
+
+ input {
+ container target {
+ description
+ "Particular configuration to edit.";
+
+ choice config-target {
+ mandatory true;
+ description
+ "The configuration target.";
+
+ leaf candidate {
+ if-feature candidate;
+ type empty;
+ description
+ "The candidate configuration is the config target.";
+ }
+ leaf running {
+ if-feature writable-running;
+ type empty;
+ description
+ "The running configuration is the config source.";
+ }
+ }
+ }
+
+ leaf default-operation {
+ type enumeration {
+ enum merge {
+ description
+ "The default operation is merge.";
+ }
+ enum replace {
+ description
+ "The default operation is replace.";
+ }
+ enum none {
+ description
+ "There is no default operation.";
+ }
+ }
+ default "merge";
+ description
+ "The default operation to use.";
+ }
+
+ leaf test-option {
+ if-feature validate;
+ type enumeration {
+ enum test-then-set {
+ description
+ "The server will test and then set if no errors.";
+ }
+ enum set {
+ description
+ "The server will set without a test first.";
+ }
+
+ enum test-only {
+ description
+ "The server will only test and not set, even
+ if there are no errors.";
+ }
+ }
+ default "test-then-set";
+ description
+ "The test option to use.";
+ }
+
+ leaf error-option {
+ type enumeration {
+ enum stop-on-error {
+ description
+ "The server will stop on errors.";
+ }
+ enum continue-on-error {
+ description
+ "The server may continue on errors.";
+ }
+ enum rollback-on-error {
+ description
+ "The server will roll back on errors.
+ This value can only be used if the 'rollback-on-error'
+ feature is supported.";
+ }
+ }
+ default "stop-on-error";
+ description
+ "The error option to use.";
+ }
+
+ choice edit-content {
+ mandatory true;
+ description
+ "The content for the edit operation.";
+
+ anyxml config {
+ description
+ "Inline Config content.";
+ }
+ leaf url {
+ if-feature url;
+ type inet:uri;
+ description
+ "URL-based config content.";
+ }
+ }
+ }
+ }
+
+ rpc copy-config {
+ description
+ "Create or replace an entire configuration datastore with the
+ contents of another complete configuration datastore.";
+
+ reference "RFC 6241, Section 7.3";
+
+ input {
+ container target {
+ description
+ "Particular configuration to copy to.";
+
+ choice config-target {
+ mandatory true;
+ description
+ "The configuration target of the copy operation.";
+
+ leaf candidate {
+ if-feature candidate;
+ type empty;
+ description
+ "The candidate configuration is the config target.";
+ }
+ leaf running {
+ if-feature writable-running;
+ type empty;
+ description
+ "The running configuration is the config target.
+ This is optional-to-implement on the server.";
+ }
+ leaf startup {
+ if-feature startup;
+ type empty;
+ description
+ "The startup configuration is the config target.";
+ }
+ leaf url {
+ if-feature url;
+ type inet:uri;
+ description
+ "The URL-based configuration is the config target.";
+ }
+ }
+ }
+
+ container source {
+ description
+ "Particular configuration to copy from.";
+
+ choice config-source {
+ mandatory true;
+ description
+ "The configuration source for the copy operation.";
+
+ leaf candidate {
+ if-feature candidate;
+ type empty;
+ description
+ "The candidate configuration is the config source.";
+ }
+ leaf running {
+ type empty;
+ description
+ "The running configuration is the config source.";
+ }
+ leaf startup {
+ if-feature startup;
+ type empty;
+ description
+ "The startup configuration is the config source.";
+ }
+ leaf url {
+ if-feature url;
+ type inet:uri;
+ description
+ "The URL-based configuration is the config source.";
+ }
+ anyxml config {
+ description
+ "Inline Config content: <config> element. Represents
+ an entire configuration datastore, not
+ a subset of the running datastore.";
+ }
+ }
+ }
+ }
+ }
+
+ rpc delete-config {
+ nacm:default-deny-all;
+ description
+ "Delete a configuration datastore.";
+
+ reference "RFC 6241, Section 7.4";
+
+ input {
+ container target {
+ description
+ "Particular configuration to delete.";
+
+ choice config-target {
+ mandatory true;
+ description
+ "The configuration target to delete.";
+
+ leaf startup {
+ if-feature startup;
+ type empty;
+ description
+ "The startup configuration is the config target.";
+ }
+ leaf url {
+ if-feature url;
+ type inet:uri;
+ description
+ "The URL-based configuration is the config target.";
+ }
+ }
+ }
+ }
+ }
+
+ rpc lock {
+ description
+ "The lock operation allows the client to lock the configuration
+ system of a device.";
+
+ reference "RFC 6241, Section 7.5";
+
+ input {
+ container target {
+ description
+ "Particular configuration to lock.";
+
+ choice config-target {
+ mandatory true;
+ description
+ "The configuration target to lock.";
+
+ leaf candidate {
+ if-feature candidate;
+ type empty;
+ description
+ "The candidate configuration is the config target.";
+ }
+ leaf running {
+ type empty;
+ description
+ "The running configuration is the config target.";
+ }
+ leaf startup {
+ if-feature startup;
+ type empty;
+ description
+ "The startup configuration is the config target.";
+ }
+ }
+ }
+ }
+ }
+
+ rpc unlock {
+ description
+ "The unlock operation is used to release a configuration lock,
+ previously obtained with the 'lock' operation.";
+
+ reference "RFC 6241, Section 7.6";
+
+ input {
+ container target {
+ description
+ "Particular configuration to unlock.";
+
+ choice config-target {
+ mandatory true;
+ description
+ "The configuration target to unlock.";
+
+ leaf candidate {
+ if-feature candidate;
+ type empty;
+ description
+ "The candidate configuration is the config target.";
+ }
+ leaf running {
+ type empty;
+ description
+ "The running configuration is the config target.";
+ }
+ leaf startup {
+ if-feature startup;
+ type empty;
+ description
+ "The startup configuration is the config target.";
+ }
+ }
+ }
+ }
+ }
+
+ rpc get {
+ description
+ "Retrieve running configuration and device state information.";
+
+ reference "RFC 6241, Section 7.7";
+
+ input {
+ anyxml filter {
+ description
+ "This parameter specifies the portion of the system
+ configuration and state data to retrieve.";
+ nc:get-filter-element-attributes;
+ }
+ }
+
+ output {
+ anyxml data {
+ description
+ "Copy of the running datastore subset and/or state
+ data that matched the filter criteria (if any).
+ An empty data container indicates that the request did not
+ produce any results.";
+ }
+ }
+ }
+
+ rpc close-session {
+ description
+ "Request graceful termination of a NETCONF session.";
+
+ reference "RFC 6241, Section 7.8";
+ }
+
+ rpc kill-session {
+ nacm:default-deny-all;
+ description
+ "Force the termination of a NETCONF session.";
+
+ reference "RFC 6241, Section 7.9";
+
+ input {
+ leaf session-id {
+ type session-id-type;
+ mandatory true;
+ description
+ "Particular session to kill.";
+ }
+ }
+ }
+
+ rpc commit {
+ if-feature candidate;
+
+ description
+ "Commit the candidate configuration as the device's new
+ current configuration.";
+
+ reference "RFC 6241, Section 8.3.4.1";
+
+ input {
+ leaf confirmed {
+ if-feature confirmed-commit;
+ type empty;
+ description
+ "Requests a confirmed commit.";
+ reference "RFC 6241, Section 8.3.4.1";
+ }
+
+ leaf confirm-timeout {
+ if-feature confirmed-commit;
+ type uint32 {
+ range "1..max";
+ }
+ units "seconds";
+ default "600"; // 10 minutes
+ description
+ "The timeout interval for a confirmed commit.";
+ reference "RFC 6241, Section 8.3.4.1";
+ }
+
+ leaf persist {
+ if-feature confirmed-commit;
+ type string;
+ description
+ "This parameter is used to make a confirmed commit
+ persistent. A persistent confirmed commit is not aborted
+ if the NETCONF session terminates. The only way to abort
+ a persistent confirmed commit is to let the timer expire,
+ or to use the <cancel-commit> operation.
+
+ The value of this parameter is a token that must be given
+ in the 'persist-id' parameter of <commit> or
+ <cancel-commit> operations in order to confirm or cancel
+ the persistent confirmed commit.
+
+ The token should be a random string.";
+ reference "RFC 6241, Section 8.3.4.1";
+ }
+
+ leaf persist-id {
+ if-feature confirmed-commit;
+ type string;
+ description
+ "This parameter is given in order to commit a persistent
+ confirmed commit. The value must be equal to the value
+ given in the 'persist' parameter to the <commit> operation.
+ If it does not match, the operation fails with an
+ 'invalid-value' error.";
+ reference "RFC 6241, Section 8.3.4.1";
+ }
+
+ }
+ }
+
+ rpc discard-changes {
+ if-feature candidate;
+
+ description
+ "Revert the candidate configuration to the current
+ running configuration.";
+ reference "RFC 6241, Section 8.3.4.2";
+ }
+
+ rpc cancel-commit {
+ if-feature confirmed-commit;
+ description
+ "This operation is used to cancel an ongoing confirmed commit.
+ If the confirmed commit is persistent, the parameter
+ 'persist-id' must be given, and it must match the value of the
+ 'persist' parameter.";
+ reference "RFC 6241, Section 8.4.4.1";
+
+ input {
+ leaf persist-id {
+ type string;
+ description
+ "This parameter is given in order to cancel a persistent
+ confirmed commit. The value must be equal to the value
+ given in the 'persist' parameter to the <commit> operation.
+ If it does not match, the operation fails with an
+ 'invalid-value' error.";
+ }
+ }
+ }
+
+ rpc validate {
+ if-feature validate;
+
+ description
+ "Validates the contents of the specified configuration.";
+
+ reference "RFC 6241, Section 8.6.4.1";
+
+ input {
+ container source {
+ description
+ "Particular configuration to validate.";
+
+ choice config-source {
+ mandatory true;
+ description
+ "The configuration source to validate.";
+
+ leaf candidate {
+ if-feature candidate;
+ type empty;
+ description
+ "The candidate configuration is the config source.";
+ }
+ leaf running {
+ type empty;
+ description
+ "The running configuration is the config source.";
+ }
+ leaf startup {
+ if-feature startup;
+ type empty;
+ description
+ "The startup configuration is the config source.";
+ }
+ leaf url {
+ if-feature url;
+ type inet:uri;
+ description
+ "The URL-based configuration is the config source.";
+ }
+ anyxml config {
+ description
+ "Inline Config content: <config> element. Represents
+ an entire configuration datastore, not
+ a subset of the running datastore.";
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/tests/yanglint/modules/modaction.yang b/tests/yanglint/modules/modaction.yang
new file mode 100644
index 0000000..5a3f92f
--- /dev/null
+++ b/tests/yanglint/modules/modaction.yang
@@ -0,0 +1,26 @@
+module modaction {
+ yang-version 1.1;
+ namespace "urn:yanglint:modaction";
+ prefix ma;
+
+ container con {
+ list ls {
+ key "lfkey";
+ leaf lfkey {
+ type string;
+ }
+ action act {
+ input {
+ leaf lfi {
+ type string;
+ }
+ }
+ output {
+ leaf lfo {
+ type int16;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/yanglint/modules/modconfig-augment.yang b/tests/yanglint/modules/modconfig-augment.yang
new file mode 100644
index 0000000..d94b366
--- /dev/null
+++ b/tests/yanglint/modules/modconfig-augment.yang
@@ -0,0 +1,15 @@
+module modconfig-augment {
+ yang-version 1.1;
+ namespace "urn:yanglint:modconfig-augment";
+ prefix "mca";
+
+ import modconfig {
+ prefix mc;
+ }
+
+ augment "/mc:mcc" {
+ leaf alf {
+ type string;
+ }
+ }
+}
diff --git a/tests/yanglint/modules/modconfig.yang b/tests/yanglint/modules/modconfig.yang
new file mode 100644
index 0000000..1d12ca6
--- /dev/null
+++ b/tests/yanglint/modules/modconfig.yang
@@ -0,0 +1,17 @@
+module modconfig {
+ namespace "urn:yanglint:modconfig";
+ prefix mc;
+
+ container mcc {
+ leaf lft {
+ type string;
+ config true;
+ mandatory true;
+ }
+ leaf lff {
+ type string;
+ config false;
+ mandatory true;
+ }
+ }
+}
diff --git a/tests/yanglint/modules/moddatanodes.yang b/tests/yanglint/modules/moddatanodes.yang
new file mode 100644
index 0000000..ae4ab20
--- /dev/null
+++ b/tests/yanglint/modules/moddatanodes.yang
@@ -0,0 +1,31 @@
+module moddatanodes {
+ yang-version 1.1;
+ namespace "urn:yanglint:moddatanodes";
+ prefix mdn;
+
+ container dnc {
+ leaf lf {
+ type string;
+ }
+ leaf-list lfl {
+ type string;
+ }
+ leaf mis {
+ type string;
+ }
+ container con {
+ list lt {
+ key "kalf kblf";
+ leaf kalf {
+ type string;
+ }
+ leaf kblf {
+ type string;
+ }
+ leaf vlf {
+ type string;
+ }
+ }
+ }
+ }
+}
diff --git a/tests/yanglint/modules/moddefault.yang b/tests/yanglint/modules/moddefault.yang
new file mode 100644
index 0000000..26570c3
--- /dev/null
+++ b/tests/yanglint/modules/moddefault.yang
@@ -0,0 +1,19 @@
+module moddefault {
+ namespace "urn:yanglint:moddefault";
+ prefix md;
+
+ container mdc {
+ leaf lf {
+ type uint16;
+ }
+ leaf di {
+ type int16;
+ default "5";
+ }
+ leaf ds {
+ type string;
+ default "str";
+ }
+ }
+
+}
diff --git a/tests/yanglint/modules/modextleafref.yang b/tests/yanglint/modules/modextleafref.yang
new file mode 100644
index 0000000..d45ec71
--- /dev/null
+++ b/tests/yanglint/modules/modextleafref.yang
@@ -0,0 +1,24 @@
+module modextleafref {
+ namespace "urn:yanglint:modextleafref";
+ prefix mel;
+
+ list ls {
+ key k;
+ leaf k {
+ type string;
+ }
+ leaf lf {
+ type uint8;
+ }
+ }
+ leaf lfr {
+ type leafref {
+ path "../ls/k";
+ }
+ }
+ leaf lfrderef {
+ type leafref {
+ path "deref(../lfr)/../lf";
+ }
+ }
+}
diff --git a/tests/yanglint/modules/modfeature.yang b/tests/yanglint/modules/modfeature.yang
new file mode 100644
index 0000000..f59d4c8
--- /dev/null
+++ b/tests/yanglint/modules/modfeature.yang
@@ -0,0 +1,7 @@
+module modfeature {
+ namespace "urn:yanglint:modfeature";
+ prefix l;
+
+ feature ftr1;
+ feature ftr2;
+}
diff --git a/tests/yanglint/modules/modimp-cwd.yang b/tests/yanglint/modules/modimp-cwd.yang
new file mode 100644
index 0000000..3249462
--- /dev/null
+++ b/tests/yanglint/modules/modimp-cwd.yang
@@ -0,0 +1,8 @@
+module modimp-cwd {
+ namespace "urn:yanglint:modimp-cwd";
+ prefix ic;
+
+ import modcwd {
+ prefix mc;
+ }
+}
diff --git a/tests/yanglint/modules/modimp-path.yang b/tests/yanglint/modules/modimp-path.yang
new file mode 100644
index 0000000..d9dbb9b
--- /dev/null
+++ b/tests/yanglint/modules/modimp-path.yang
@@ -0,0 +1,8 @@
+module modimp-path {
+ namespace "urn:yanglint:modimp-path";
+ prefix ip;
+
+ import modpath {
+ prefix mp;
+ }
+}
diff --git a/tests/yanglint/modules/modimp-type.yang b/tests/yanglint/modules/modimp-type.yang
new file mode 100644
index 0000000..ec21d31
--- /dev/null
+++ b/tests/yanglint/modules/modimp-type.yang
@@ -0,0 +1,12 @@
+module modimp-type {
+ namespace "urn:yanglint:modimp-type";
+ prefix mit;
+
+ import modtypedef {
+ prefix mtd;
+ }
+
+ leaf lf {
+ type mtd:mui8;
+ }
+}
diff --git a/tests/yanglint/modules/modinclude.yang b/tests/yanglint/modules/modinclude.yang
new file mode 100644
index 0000000..849d43f
--- /dev/null
+++ b/tests/yanglint/modules/modinclude.yang
@@ -0,0 +1,9 @@
+module modinclude {
+ yang-version 1.1;
+ namespace "urn:yanglint:modinclude";
+ prefix mi;
+
+ include "modsub";
+
+ container mic;
+}
diff --git a/tests/yanglint/modules/modleaf.yang b/tests/yanglint/modules/modleaf.yang
new file mode 100644
index 0000000..48ce786
--- /dev/null
+++ b/tests/yanglint/modules/modleaf.yang
@@ -0,0 +1,8 @@
+module modleaf {
+ namespace "urn:yanglint:modleaf";
+ prefix l;
+
+ leaf lfl {
+ type uint16;
+ }
+}
diff --git a/tests/yanglint/modules/modleafref.yang b/tests/yanglint/modules/modleafref.yang
new file mode 100644
index 0000000..f86fb3f
--- /dev/null
+++ b/tests/yanglint/modules/modleafref.yang
@@ -0,0 +1,14 @@
+module modleafref {
+ namespace "urn:yanglint:modleafref";
+ prefix m;
+
+ import modleaf {
+ prefix ml;
+ }
+
+ leaf lfr {
+ type leafref {
+ path "/ml:lfl";
+ }
+ }
+}
diff --git a/tests/yanglint/modules/modmandatory.yang b/tests/yanglint/modules/modmandatory.yang
new file mode 100644
index 0000000..4d48540
--- /dev/null
+++ b/tests/yanglint/modules/modmandatory.yang
@@ -0,0 +1,14 @@
+module modmandatory {
+ namespace "urn:yanglint:modmandatory";
+ prefix mm;
+
+ container mmc {
+ leaf lft {
+ type int16;
+ mandatory true;
+ }
+ leaf lff {
+ type int16;
+ }
+ }
+}
diff --git a/tests/yanglint/modules/modmerge.yang b/tests/yanglint/modules/modmerge.yang
new file mode 100644
index 0000000..60fd75c
--- /dev/null
+++ b/tests/yanglint/modules/modmerge.yang
@@ -0,0 +1,21 @@
+module modmerge {
+ namespace "urn:yanglint:modmerge";
+ prefix mm;
+
+ container mmc {
+ leaf en {
+ type enumeration {
+ enum zero;
+ enum one;
+ }
+ }
+ leaf lm {
+ type int16;
+ must "../en != 'zero'";
+ }
+ leaf lf {
+ type string;
+ }
+ }
+
+}
diff --git a/tests/yanglint/modules/modmust.yang b/tests/yanglint/modules/modmust.yang
new file mode 100644
index 0000000..99971bd
--- /dev/null
+++ b/tests/yanglint/modules/modmust.yang
@@ -0,0 +1,13 @@
+module modmust {
+ namespace "urn:yanglint:modmust";
+ prefix m;
+
+ import modleaf {
+ prefix ml;
+ }
+
+ leaf lfm {
+ type string;
+ must "/ml:lfl > 0";
+ }
+}
diff --git a/tests/yanglint/modules/modnotif.yang b/tests/yanglint/modules/modnotif.yang
new file mode 100644
index 0000000..a2155a0
--- /dev/null
+++ b/tests/yanglint/modules/modnotif.yang
@@ -0,0 +1,19 @@
+module modnotif {
+ yang-version 1.1;
+ namespace "urn:yanglint:modnotif";
+ prefix mn;
+
+ container con {
+ notification nfn {
+ leaf lf {
+ type string;
+ }
+ }
+ }
+
+ notification nfg {
+ leaf lf {
+ type string;
+ }
+ }
+}
diff --git a/tests/yanglint/modules/modoper-leafref.yang b/tests/yanglint/modules/modoper-leafref.yang
new file mode 100644
index 0000000..36a1124
--- /dev/null
+++ b/tests/yanglint/modules/modoper-leafref.yang
@@ -0,0 +1,68 @@
+module modoper-leafref {
+ yang-version 1.1;
+ namespace "urn:yanglint:modoper-leafref";
+ prefix mol;
+
+ import modconfig {
+ prefix mc;
+ }
+
+ container cond {
+ list list {
+ key "klf";
+ leaf klf {
+ type string;
+ }
+ action act {
+ input {
+ leaf lfi {
+ type leafref {
+ path "/mc:mcc/mc:lft";
+ }
+ }
+ }
+ output {
+ leaf lfo {
+ type leafref {
+ path "/mc:mcc/mc:lft";
+ }
+ }
+ }
+ }
+ notification notif {
+ leaf lfn {
+ type leafref {
+ path "/mc:mcc/mc:lft";
+ }
+ }
+ }
+ }
+ }
+
+ rpc rpcg {
+ input {
+ leaf lfi {
+ type leafref {
+ path "/mc:mcc/mc:lft";
+ }
+ }
+ }
+ output {
+ container cono {
+ leaf lfo {
+ type leafref {
+ path "/mc:mcc/mc:lft";
+ }
+ }
+ }
+ }
+ }
+
+ notification notifg {
+ leaf lfr {
+ type leafref {
+ path "/mc:mcc/mc:lft";
+ }
+ }
+ }
+}
diff --git a/tests/yanglint/modules/modpath.yang b/tests/yanglint/modules/modpath.yang
new file mode 100644
index 0000000..da099a2
--- /dev/null
+++ b/tests/yanglint/modules/modpath.yang
@@ -0,0 +1,4 @@
+module modpath {
+ namespace "urn:yanglint:modpath";
+ prefix mp;
+}
diff --git a/tests/yanglint/modules/modrpc.yang b/tests/yanglint/modules/modrpc.yang
new file mode 100644
index 0000000..dc0cced
--- /dev/null
+++ b/tests/yanglint/modules/modrpc.yang
@@ -0,0 +1,19 @@
+module modrpc {
+ namespace "urn:yanglint:modrpc";
+ prefix mr;
+
+ rpc rpc {
+ input {
+ leaf lfi {
+ type string;
+ }
+ }
+ output {
+ container con {
+ leaf lfo {
+ type int16;
+ }
+ }
+ }
+ }
+}
diff --git a/tests/yanglint/modules/modsm-augment.yang b/tests/yanglint/modules/modsm-augment.yang
new file mode 100644
index 0000000..5d16fbd
--- /dev/null
+++ b/tests/yanglint/modules/modsm-augment.yang
@@ -0,0 +1,15 @@
+module modsm-augment {
+ yang-version 1.1;
+ namespace "urn:yanglint:modsm-augment";
+ prefix "msa";
+
+ import modsm {
+ prefix msm;
+ }
+
+ augment "/msm:root" {
+ leaf alf {
+ type string;
+ }
+ }
+}
diff --git a/tests/yanglint/modules/modsm.yang b/tests/yanglint/modules/modsm.yang
new file mode 100644
index 0000000..dfe8830
--- /dev/null
+++ b/tests/yanglint/modules/modsm.yang
@@ -0,0 +1,13 @@
+module modsm {
+ yang-version 1.1;
+ namespace "urn:yanglint:modsm";
+ prefix "msm";
+
+ import ietf-yang-schema-mount {
+ prefix sm;
+ }
+
+ container root {
+ sm:mount-point "root";
+ }
+}
diff --git a/tests/yanglint/modules/modsub.yang b/tests/yanglint/modules/modsub.yang
new file mode 100644
index 0000000..79d9286
--- /dev/null
+++ b/tests/yanglint/modules/modsub.yang
@@ -0,0 +1,8 @@
+submodule modsub {
+ yang-version 1.1;
+ belongs-to modinclude {
+ prefix mi;
+ }
+
+ container msc;
+}
diff --git a/tests/yanglint/modules/modtypedef.yang b/tests/yanglint/modules/modtypedef.yang
new file mode 100644
index 0000000..ea09c95
--- /dev/null
+++ b/tests/yanglint/modules/modtypedef.yang
@@ -0,0 +1,8 @@
+module modtypedef {
+ namespace "urn:yanglint:typedef";
+ prefix mt;
+
+ typedef mui8 {
+ type uint8;
+ }
+}
diff --git a/tests/yanglint/non-interactive/all.tcl b/tests/yanglint/non-interactive/all.tcl
new file mode 100644
index 0000000..998c03a
--- /dev/null
+++ b/tests/yanglint/non-interactive/all.tcl
@@ -0,0 +1,15 @@
+package require tcltest
+
+# Hook to determine if any of the tests failed.
+# Sets a global variable exitCode to 1 if any test fails otherwise it is set to 0.
+proc tcltest::cleanupTestsHook {} {
+ variable numTests
+ set ::exitCode [expr {$numTests(Failed) > 0}]
+}
+
+if {[info exists ::env(TESTS_DIR)]} {
+ tcltest::configure -testdir "$env(TESTS_DIR)/non-interactive"
+}
+
+tcltest::runAllTests
+exit $exitCode
diff --git a/tests/yanglint/non-interactive/data_default.test b/tests/yanglint/non-interactive/data_default.test
new file mode 100644
index 0000000..be19d72
--- /dev/null
+++ b/tests/yanglint/non-interactive/data_default.test
@@ -0,0 +1,31 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/non-interactive/ly.tcl" : "ly.tcl"}]
+
+set mods "$::env(YANG_MODULES_DIR)/ietf-netconf-with-defaults@2011-06-01.yang $::env(YANG_MODULES_DIR)/moddefault.yang"
+set data "$::env(TESTS_DIR)/data/moddefault.xml"
+
+test data_default_not_set {Print data without --default parameter} {
+ ly_cmd "-f xml $mods $data" "</lf>.*</di>\n</mdc>"
+ ly_cmd "-f json $mods $data" "lf\".*di\"\[^\"]*"
+} {}
+
+test data_default_all {data --default all} {
+ ly_cmd "-d all -f xml $mods $data" "</lf>.*</di>.*</ds>\n</mdc>"
+ ly_cmd "-d all -f json $mods $data" "lf\".*di\".*ds\"\[^\"]*"
+} {}
+
+test data_default_all_tagged {data --default all-tagged} {
+ ly_cmd "-d all-tagged -f xml $mods $data" "</lf>.*<di.*default.*</di>.*<ds.*default.*</ds>\n</mdc>"
+ ly_cmd "-d all-tagged -f json $mods $data" "lf\".*di\".*ds\".*@ds\".*default\"\[^\"]*"
+} {}
+
+test data_default_trim {data --default trim} {
+ ly_cmd "-d trim -f xml $mods $data" "</lf>\n</mdc>"
+ ly_cmd "-d trim -f json $mods $data" "lf\"\[^\"]*"
+} {}
+
+test data_default_implicit_tagged {data --default implicit-tagged} {
+ ly_cmd "-d implicit-tagged -f xml $mods $data" "</lf>.*<di>5</di>.*<ds.*default.*</ds>\n</mdc>"
+ ly_cmd "-d implicit-tagged -f json $mods $data" "lf\".*di\"\[^@]*ds\".*default\"\[^\"]*"
+} {}
+
+cleanupTests
diff --git a/tests/yanglint/non-interactive/data_in_format.test b/tests/yanglint/non-interactive/data_in_format.test
new file mode 100644
index 0000000..f1336dd
--- /dev/null
+++ b/tests/yanglint/non-interactive/data_in_format.test
@@ -0,0 +1,18 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/non-interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir $::env(YANG_MODULES_DIR)
+set ddir $::env(TESTS_DIR)/data
+
+test data_in_format_xml {--in-format xml} {
+ ly_cmd "-I xml $mdir/modleaf.yang $ddir/modleaf.dxml"
+ ly_cmd_err "-I json $mdir/modleaf.yang $ddir/modleaf.dxml" "Failed to parse"
+ ly_cmd_err "-I lyb $mdir/modleaf.yang $ddir/modleaf.dxml" "Failed to parse"
+} {}
+
+test data_in_format_json {--in-format json} {
+ ly_cmd "-I json $mdir/modleaf.yang $ddir/modleaf.djson"
+ ly_cmd_err "-I xml $mdir/modleaf.yang $ddir/modleaf.djson" "Failed to parse"
+ ly_cmd_err "-I lyb $mdir/modleaf.yang $ddir/modleaf.djson" "Failed to parse"
+} {}
+
+cleanupTests
diff --git a/tests/yanglint/non-interactive/data_merge.test b/tests/yanglint/non-interactive/data_merge.test
new file mode 100644
index 0000000..4ecfcee
--- /dev/null
+++ b/tests/yanglint/non-interactive/data_merge.test
@@ -0,0 +1,28 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/non-interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir $::env(YANG_MODULES_DIR)
+set ddir $::env(TESTS_DIR)/data
+
+test data_merge_basic {Data is merged and the node is added} {
+ ly_cmd "-m -f xml $mdir/modmerge.yang $ddir/modmerge.xml $ddir/modmerge3.xml" "<en>.*<lm>.*<lf>"
+} {}
+
+test data_merge_validation_failed {Data is merged but validation failed.} {
+ ly_cmd "$mdir/modmerge.yang $ddir/modmerge.xml"
+ ly_cmd "$mdir/modmerge.yang $ddir/modmerge2.xml"
+ ly_cmd "-m $mdir/modmerge.yang $ddir/modmerge2.xml $ddir/modmerge.xml"
+ ly_cmd_err "-m $mdir/modmerge.yang $ddir/modmerge.xml $ddir/modmerge2.xml" "Merged data are not valid"
+} {}
+
+test data_merge_dataconfig {The merge option has effect only for 'data' and 'config' TYPEs} {
+ set wrn1 "option has effect only for"
+ ly_cmd_wrn "-m -t rpc $mdir/modrpc.yang $ddir/modrpc.xml $ddir/modrpc.xml" $wrn1
+ ly_cmd_wrn "-m -t notif $mdir/modnotif.yang $ddir/modnotif2.xml $ddir/modnotif2.xml" $wrn1
+ ly_cmd_wrn "-m -t get $mdir/modconfig.yang $mdir/modleaf.yang $ddir/modleaf.xml $ddir/modconfig.xml" $wrn1
+ ly_cmd_wrn "-m -t getconfig $mdir/modconfig.yang $mdir/modleaf.yang $ddir/modleaf.xml $ddir/modconfig2.xml" $wrn1
+ ly_cmd_wrn "-m -t edit $mdir/modconfig.yang $mdir/modleaf.yang $ddir/modleaf.xml $ddir/modconfig2.xml" $wrn1
+ ly_cmd "-m -t config $mdir/modconfig.yang $mdir/modleaf.yang $ddir/modleaf.xml $ddir/modconfig2.xml"
+ ly_cmd "-m -t data $mdir/modconfig.yang $mdir/modleaf.yang $ddir/modleaf.xml $ddir/modconfig.xml"
+} {}
+
+cleanupTests
diff --git a/tests/yanglint/non-interactive/data_not_strict.test b/tests/yanglint/non-interactive/data_not_strict.test
new file mode 100644
index 0000000..b91eed8
--- /dev/null
+++ b/tests/yanglint/non-interactive/data_not_strict.test
@@ -0,0 +1,20 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/non-interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir $::env(YANG_MODULES_DIR)
+set ddir $::env(TESTS_DIR)/data
+
+test data_no_strict_basic {} {
+ ly_cmd_err "$ddir/modmandatory.xml $mdir/modleaf.yang" "No module with namespace \"urn:yanglint:modmandatory\" in the context."
+ ly_cmd "-n $ddir/modmandatory.xml $mdir/modleaf.yang"
+} {}
+
+test data_no_strict_invalid_data {validation with --no-strict but data are invalid} {
+ set errmsg "Mandatory node \"lft\" instance does not exist."
+ ly_cmd_err "-n $ddir/modmandatory_invalid.xml $mdir/modmandatory.yang" $errmsg
+} {}
+
+test data_no_strict_ignore_invalid_data {--no-strict ignore invalid data if no schema is provided} {
+ ly_cmd "-f xml -n $ddir/modmandatory_invalid.xml $ddir/modleaf.xml $mdir/modleaf.yang" "modleaf.*</lfl>$"
+} {}
+
+cleanupTests
diff --git a/tests/yanglint/non-interactive/data_operational.test b/tests/yanglint/non-interactive/data_operational.test
new file mode 100644
index 0000000..82e861e
--- /dev/null
+++ b/tests/yanglint/non-interactive/data_operational.test
@@ -0,0 +1,62 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/non-interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir "$::env(YANG_MODULES_DIR)"
+set ddir "$::env(TESTS_DIR)/data"
+set err1 "Operational datastore takes effect only with RPCs/Actions/Replies/Notification input data types"
+
+test data_operational_twice {it is not allowed to specify more than one --operational parameter} {
+ ly_cmd_err "-t notif -O $ddir/modconfig.xml -O $ddir/modleaf.xml" "cannot be set multiple times"
+} {}
+
+test data_operational_no_type {--operational should be with parameter --type} {
+ ly_cmd_err "-O $ddir/modconfig.xml $mdir/modoper-leafref.yang $ddir/modoper_leafref_notif.xml" $err1
+} {}
+
+test data_operational_missing {--operational is omitted and the datastore contents is in the data file} {
+ ly_cmd_err "$mdir/modoper-leafref.yang $ddir/modoper_leafref_notif_err.xml" "Failed to parse input data file"
+} {}
+
+test data_operational_wrong_type {data are not defined as an operation} {
+ ly_cmd_wrn "-t data -O $ddir/modconfig.xml $mdir/modleaf.yang $ddir/modleaf.xml" $err1
+} {}
+
+test data_operational_datastore_with_unknown_data {unknown data are ignored} {
+ ly_cmd "-t rpc -O $ddir/modmandatory_invalid.xml $mdir/modrpc.yang $ddir/modrpc.xml"
+} {}
+
+test data_operational_empty_datastore {datastore is considered empty because it contains unknown data} {
+ ly_cmd "-t rpc -O $ddir/modmandatory_invalid.xml $mdir/modrpc.yang $ddir/modrpc.xml"
+ set msg "parent \"/modnotif:con\" not found in the operational data"
+ ly_cmd_err "-t notif -O $ddir/modmandatory_invalid.xml $mdir/modnotif.yang $ddir/modnotif.xml" $msg
+} {}
+
+test data_operational_notif_leafref {--operational data is referenced from notification-leafref} {
+ ly_cmd "-t notif -O $ddir/modconfig.xml $mdir/modoper-leafref.yang $ddir/modoper_leafref_notif.xml"
+} {}
+
+test data_operational_nested_notif_leafref {--operational data is referenced from nested-notification-leafref} {
+ ly_cmd "-t notif -O $ddir/modoper_leafref_ds.xml $mdir/modoper-leafref.yang $ddir/modoper_leafref_notif2.xml"
+} {}
+
+test data_operational_nested_notif_parent_missing {--operational data are invalid due to missing parent node} {
+ set msg "klf='key_val']\" not found in the operational data"
+ ly_cmd_err "-t notif -O $ddir/modconfig.xml $mdir/modoper-leafref.yang $ddir/modoper_leafref_notif2.xml" $msg
+} {}
+
+test data_operational_action_leafref {--operational data is referenced from action-leafref} {
+ ly_cmd "-t rpc -O $ddir/modoper_leafref_ds.xml $mdir/modoper-leafref.yang $ddir/modoper_leafref_action.xml"
+} {}
+
+test data_operational_action_reply_leafref {--operational data is referenced from action-leafref output} {
+ ly_cmd "-t reply -O $ddir/modoper_leafref_ds.xml $mdir/modoper-leafref.yang $ddir/modoper_leafref_action_reply.xml"
+} {}
+
+test data_operational_rpc_leafref {--operational data is referenced from rpc-leafref} {
+ ly_cmd "-t rpc -O $ddir/modconfig.xml $mdir/modoper-leafref.yang $ddir/modoper_leafref_rpc.xml"
+} {}
+
+test data_operational_rpc_reply_leafref {--operational data is referenced from rpc-leafref output} {
+ ly_cmd "-t reply -O $ddir/modconfig.xml $mdir/modoper-leafref.yang $ddir/modoper_leafref_rpc_reply.xml"
+} {}
+
+cleanupTests
diff --git a/tests/yanglint/non-interactive/data_present.test b/tests/yanglint/non-interactive/data_present.test
new file mode 100644
index 0000000..81aac14
--- /dev/null
+++ b/tests/yanglint/non-interactive/data_present.test
@@ -0,0 +1,25 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/non-interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir $::env(YANG_MODULES_DIR)
+set ddir $::env(TESTS_DIR)/data
+
+test data_present_via_mandatory {validation of mandatory-stmt will pass only with the --present} {
+ set mods "$mdir/modleaf.yang $mdir/modmandatory.yang"
+ ly_cmd_err "$ddir/modleaf.xml $mods" "Mandatory node \"lft\" instance does not exist."
+ ly_cmd "-e $ddir/modleaf.xml $mods"
+} {}
+
+test data_present_merge {validation with --present and --merge} {
+ set mods "$mdir/modleaf.yang $mdir/modmandatory.yang $mdir/moddefault.yang"
+ set data "$ddir/modleaf.xml $ddir/moddefault.xml"
+ ly_cmd_err "-m $data $mods" "Mandatory node \"lft\" instance does not exist."
+ ly_cmd "-m -e $data $mods"
+} {}
+
+test data_present_merge_invalid {using --present and --merge but data are invalid} {
+ set mods "$mdir/modleaf.yang $mdir/modmandatory.yang"
+ set data "$ddir/modleaf.xml $ddir/modmandatory_invalid.xml"
+ ly_cmd_err "-e -m $data $mods" "Mandatory node \"lft\" instance does not exist."
+} {}
+
+cleanupTests
diff --git a/tests/yanglint/non-interactive/data_type.test b/tests/yanglint/non-interactive/data_type.test
new file mode 100644
index 0000000..e3691d7
--- /dev/null
+++ b/tests/yanglint/non-interactive/data_type.test
@@ -0,0 +1,107 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/non-interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir "$::env(YANG_MODULES_DIR)"
+set ddir "$::env(TESTS_DIR)/data"
+set modnc "$mdir/ietf-netconf@2011-06-01.yang"
+
+test data_type_data {data --type data} {
+ ly_cmd "-t data $mdir/modconfig.yang $ddir/modconfig.xml"
+} {}
+
+test data_type_config {data --type config} {
+ ly_cmd_err "-t config $mdir/modconfig.yang $ddir/modconfig.xml" "Unexpected data state node \"lff\""
+ ly_cmd "-t config $mdir/modconfig.yang $ddir/modconfig2.xml"
+} {}
+
+test data_type_get {data --type get} {
+ ly_cmd_err "-t data $mdir/modleafref.yang $ddir/modleafref2.xml" "Invalid leafref value"
+ ly_cmd "-t get $mdir/modleafref.yang $ddir/modleafref2.xml"
+} {}
+
+test data_type_getconfig_no_state {No state node for data --type getconfig} {
+ ly_cmd_err "-t getconfig $mdir/modconfig.yang $ddir/modconfig.xml" "Unexpected data state node \"lff\""
+ ly_cmd "-t getconfig $mdir/modconfig.yang $ddir/modconfig2.xml"
+} {}
+
+test data_type_getconfig_parse_only {No validation performed for data --type getconfig} {
+ ly_cmd_err "-t data $mdir/modleafref.yang $ddir/modleafref2.xml" "Invalid leafref value"
+ ly_cmd "-t getconfig $mdir/modleafref.yang $ddir/modleafref2.xml"
+} {}
+
+test data_type_edit_no_state {No state node for data --type edit} {
+ ly_cmd_err "-t edit $mdir/modconfig.yang $ddir/modconfig.xml" "Unexpected data state node \"lff\""
+ ly_cmd "-t edit $mdir/modconfig.yang $ddir/modconfig2.xml"
+} {}
+
+test data_type_edit_parse_only {No validation performed for data --type edit} {
+ ly_cmd_err "-t data $mdir/modleafref.yang $ddir/modleafref2.xml" "Invalid leafref value"
+ ly_cmd "-t edit $mdir/modleafref.yang $ddir/modleafref2.xml"
+} {}
+
+test data_type_rpc {Validation of rpc-statement by data --type rpc} {
+ ly_cmd_err "-t rpc $mdir/modleaf.yang $ddir/modleaf.xml" "Missing the operation node."
+ ly_cmd "-t rpc $mdir/modrpc.yang $ddir/modrpc.xml"
+} {}
+
+test data_type_rpc_nc {Validation of rpc-statement by data --type nc-rpc} {
+ ly_cmd_err "-t nc-rpc $modnc $mdir/modleaf.yang $ddir/modleaf.xml" "Missing NETCONF <rpc> envelope"
+ ly_cmd "-t nc-rpc $modnc $mdir/modrpc.yang $ddir/modrpc_nc.xml"
+} {}
+
+test data_type_rpc_reply {Validation of rpc-reply by data --type reply} {
+ ly_cmd_err "-t rpc $mdir/modleaf.yang $ddir/modleaf.xml" "Missing the operation node."
+ ly_cmd_wrn "-t reply -R $ddir/modrpc.xml $mdir/modrpc.yang $ddir/modrpc_reply.xml" "needed only for NETCONF"
+ ly_cmd "-t reply $mdir/modrpc.yang $ddir/modrpc_reply.xml"
+} {}
+
+test data_type_rpc_reply_nc {Validation of rpc-reply by data --type nc-reply} {
+ set err1 "Missing NETCONF <rpc-reply> envelope"
+ ly_cmd_err "-t nc-reply -R $ddir/modrpc_nc.xml $mdir/modrpc.yang $mdir/modleaf.yang $ddir/modleaf.xml" $err1
+ ly_cmd_err "-t nc-reply $mdir/modrpc.yang $ddir/modrpc_reply_nc.xml" "Missing source RPC"
+ ly_cmd "-t nc-reply -R $ddir/modrpc_nc.xml $mdir/modrpc.yang $ddir/modrpc_reply_nc.xml"
+} {}
+
+test data_type_rpc_action {Validation of action-statement by data --type rpc} {
+ ly_cmd_err "-t rpc $mdir/modleaf.yang $ddir/modleaf.xml" "Missing the operation node."
+ ly_cmd "-t rpc -O $ddir/modaction_ds.xml $mdir/modaction.yang $ddir/modaction.xml"
+} {}
+
+test data_type_rpc_action_nc {Validation of action-statement by data --type nc-rpc} {
+ ly_cmd_err "-t nc-rpc $mdir/modleaf.yang $ddir/modleaf.xml" "Missing NETCONF <rpc> envelope"
+ ly_cmd "-t nc-rpc -O $ddir/modaction_ds.xml $mdir/modaction.yang $ddir/modaction_nc.xml"
+} {}
+
+test data_type_rpc_action_reply {Validation of action-reply by data --type reply} {
+ ly_cmd_err "-t rpc $mdir/modleaf.yang $ddir/modleaf.xml" "Missing the operation node."
+ ly_cmd "-t reply -O $ddir/modaction_ds.xml $mdir/modaction.yang $ddir/modaction_reply.xml"
+} {}
+
+test data_type_rpc_action_reply_nc {Validation of action-reply by data --type nc-reply} {
+ set err1 "Missing NETCONF <rpc-reply> envelope"
+ set err2 "operational parameter needed"
+ ly_cmd_err "-t nc-reply -R $ddir/modaction_nc.xml $mdir/modaction.yang $mdir/modleaf.yang $ddir/modleaf.xml" $err1
+ ly_cmd_err "-t nc-reply $mdir/modaction.yang $ddir/modaction_reply_nc.xml" "Missing source RPC"
+ ly_cmd_err "-t nc-reply -R $ddir/modaction_nc.xml $mdir/modaction.yang $ddir/modaction_reply_nc.xml" $err2
+ ly_cmd "-t nc-reply -O $ddir/modaction_ds.xml -R $ddir/modaction_nc.xml $mdir/modaction.yang $ddir/modaction_reply_nc.xml"
+} {}
+
+test data_type_notif {Validation of notification-statement by data --type notif} {
+ ly_cmd_err "-t notif $mdir/modleaf.yang $ddir/modleaf.xml" "Missing the operation node."
+ ly_cmd "-t notif $mdir/modnotif.yang $ddir/modnotif2.xml"
+} {}
+
+test data_type_notif_nc {Validation of notification-statement by data --type nc-notif} {
+ ly_cmd_err "-t nc-notif $modnc $mdir/modleaf.yang $ddir/modleaf.xml" "Missing NETCONF <notification> envelope"
+ ly_cmd "-t nc-notif $modnc $mdir/modnotif.yang $ddir/modnotif2_nc.xml"
+} {}
+
+test data_type_notif_nested {Validation of nested-notification-statement by data --type notif} {
+ ly_cmd "-t notif -O $ddir/modnotif_ds.xml $mdir/modnotif.yang $ddir/modnotif.xml"
+} {}
+
+test data_type_notif_nested_nc {Validation of nested-notification-statement by data --type nc-notif} {
+ ly_cmd_err "-t nc-notif $modnc $mdir/modleaf.yang $ddir/modleaf.xml" "Missing NETCONF <notification> envelope"
+ ly_cmd "-t nc-notif -O $ddir/modnotif_ds.xml $modnc $mdir/modnotif.yang $ddir/modnotif_nc.xml"
+} {}
+
+cleanupTests
diff --git a/tests/yanglint/non-interactive/data_xpath.test b/tests/yanglint/non-interactive/data_xpath.test
new file mode 100644
index 0000000..1d96106
--- /dev/null
+++ b/tests/yanglint/non-interactive/data_xpath.test
@@ -0,0 +1,42 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/non-interactive/ly.tcl" : "ly.tcl"}]
+
+set mod "$::env(YANG_MODULES_DIR)/moddatanodes.yang"
+set data "$::env(TESTS_DIR)/data/moddatanodes.xml"
+
+test data_xpath_empty {--data-path to missing node} {
+ ly_cmd "-E /moddatanodes:dnc/mis $mod $data" "Empty"
+} {}
+
+test data_xpath_leaf {--xpath to leaf node} {
+ ly_cmd "-E /moddatanodes:dnc/lf $mod $data" "leaf \"lf\" \\(value: \"x\"\\)"
+} {}
+
+test data_xpath_leaflist {--xpath to leaf-list node} {
+ set r1 "leaf-list \"lfl\" \\(value: \"1\"\\)"
+ set r2 "leaf-list \"lfl\" \\(value: \"2\"\\)"
+ ly_cmd "-E /moddatanodes:dnc/lfl $mod $data" "$r1\n $r2"
+} {}
+
+test data_xpath_list {--xpath to list} {
+ set r1 "list \"lt\" \\(\"kalf\": \"ka1\"; \"kblf\": \"kb1\";\\)"
+ set r2 "list \"lt\" \\(\"kalf\": \"ka2\"; \"kblf\": \"kb2\";\\)"
+ ly_cmd "-E /moddatanodes:dnc/con/lt $mod $data" "$r1\n $r2"
+} {}
+
+test data_xpath_container {--xpath to container} {
+ ly_cmd "-E /moddatanodes:dnc/con $mod $data" "container \"con\""
+} {}
+
+test data_xpath_wrong_path {--xpath to a non-existent node} {
+ ly_cmd_err "-E /moddatanodes:dnc/wrng $mod $data" "xpath failed"
+} {}
+
+test data_xpath_err_format {--xpath cannot be combined with --format} {
+ ly_cmd_err "-f xml -E /moddatanodes:dnc/lf $mod $data" "option cannot be combined"
+} {}
+
+test data_xpath_err_default {--xpath cannot be combined with --default} {
+ ly_cmd_err "-d all -E /moddatanodes:dnc/lf $mod $data" "option cannot be combined"
+} {}
+
+cleanupTests
diff --git a/tests/yanglint/non-interactive/debug.test b/tests/yanglint/non-interactive/debug.test
new file mode 100644
index 0000000..4543acb
--- /dev/null
+++ b/tests/yanglint/non-interactive/debug.test
@@ -0,0 +1,25 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/non-interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir $::env(YANG_MODULES_DIR)
+
+test debug_dict {Check debug message DICT} {
+-constraints {[ly_opt_exists "-G"]} -body {
+ ly_cmd_wrn "-V -V -G dict $mdir/modleaf.yang" "DICT"
+}}
+
+test debug_xpath {Check debug message XPATH} {
+-constraints {[ly_opt_exists "-G"]} -body {
+ ly_cmd_wrn "-V -V -G xpath $mdir/modmust.yang" "XPATH"
+}}
+
+test debug_dep_sets {Check debug message DEPSETS} {
+-constraints {[ly_opt_exists "-G"]} -body {
+ ly_cmd_wrn "-V -V -G dep-sets $mdir/modleaf.yang" "DEPSETS"
+}}
+
+test debug_depsets_xpath {Check debug message DEPSETS and XPATH} {
+-constraints {[ly_opt_exists "-G"]} -body {
+ ly_cmd_wrn "-V -V -G dep-sets,xpath $mdir/modmust.yang" "DEPSETS.*XPATH"
+}}
+
+cleanupTests
diff --git a/tests/yanglint/non-interactive/disabled_searchdir.test b/tests/yanglint/non-interactive/disabled_searchdir.test
new file mode 100644
index 0000000..49fe13e
--- /dev/null
+++ b/tests/yanglint/non-interactive/disabled_searchdir.test
@@ -0,0 +1,18 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/non-interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir $env(YANG_MODULES_DIR)
+
+# Test should be skipped if called by ctest.
+test disable_searchdir_once {Unsuccessfully imports module due to disabled cwd searching} {
+-constraints {!ctest} -body {
+ ly_cmd "$mdir/modimp-cwd.yang"
+ ly_cmd_err "-D $mdir/modimp-cwd.yang" "not found in local searchdirs"
+}}
+
+test disable_searchdir_twice {Unsuccessfully imports module due to -D -D} {
+ ly_cmd "$mdir/ietf-ip.yang"
+ ly_cmd_err "-D -D $mdir/ietf-ip.yang" "Loading \"ietf-interfaces\" module failed."
+} {}
+
+cleanupTests
+
diff --git a/tests/yanglint/non-interactive/ext_data.test b/tests/yanglint/non-interactive/ext_data.test
new file mode 100644
index 0000000..d4e3c44
--- /dev/null
+++ b/tests/yanglint/non-interactive/ext_data.test
@@ -0,0 +1,29 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/non-interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir "$::env(YANG_MODULES_DIR)"
+set ddir "$::env(TESTS_DIR)/data"
+
+test ext_data_schema_mount_tree {Print tree output of a model with Schema Mount} {
+ # mounting node lfl from modleaf.yang into modsm.yang
+ set out1 "--mp root.*--rw lfl/"
+ ly_cmd "-f tree -p $mdir -y -x $ddir/modsm_ctx_ext.xml $mdir/modsm.yang" $out1
+} {}
+
+test ext_data_schema_mount_tree_yanglibfile {Print tree output of a model with Schema Mount and --yang-library-file} {
+ # yang-library-file context contains an augment node 'alf' for modsm
+ set out1 "--mp root.*--rw lfl/.*--rw msa:alf?"
+ ly_cmd "-f tree -p $mdir -Y $ddir/modsm_ctx_main.xml -x $ddir/modsm_ctx_ext.xml $mdir/modsm.yang" $out1
+} {}
+
+test ext_data_schema_mount_xml {Validating and printing mounted data} {
+ ly_cmd "-f xml -t config -p $mdir -y -x $ddir/modsm_ctx_ext.xml $mdir/modsm.yang $ddir/modsm.xml" "</lfl>"
+} {}
+
+test ext_data_schema_mount_xml_yanglibfile {Validating and printing mounted data with --yang-library-file} {
+ set yanglibfile "$ddir/modsm_ctx_main.xml"
+ set extdata "$ddir/modsm_ctx_ext.xml"
+ set out1 "</lfl>.*</alf>"
+ ly_cmd "-f xml -t config -p $mdir -Y $yanglibfile -x $extdata $mdir/modsm.yang $ddir/modsm2.xml" $out1
+} {}
+
+cleanupTests
diff --git a/tests/yanglint/non-interactive/extended_leafref.test b/tests/yanglint/non-interactive/extended_leafref.test
new file mode 100644
index 0000000..5e1a90e
--- /dev/null
+++ b/tests/yanglint/non-interactive/extended_leafref.test
@@ -0,0 +1,13 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/non-interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir $::env(YANG_MODULES_DIR)
+
+test extended_leafref_enabled {Valid module with --extended-leafref option} {
+ ly_cmd "-X $mdir/modextleafref.yang"
+} {}
+
+test extended_leafref_disabled {Expected error if --extended-leafref is not set} {
+ ly_cmd_err "$mdir/modextleafref.yang" "Unexpected XPath token \"FunctionName\""
+} {}
+
+cleanupTests
diff --git a/tests/yanglint/non-interactive/format.test b/tests/yanglint/non-interactive/format.test
new file mode 100644
index 0000000..8df5544
--- /dev/null
+++ b/tests/yanglint/non-interactive/format.test
@@ -0,0 +1,72 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/non-interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir $::env(YANG_MODULES_DIR)
+set ddir $::env(TESTS_DIR)/data
+set ipv6_path "/ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address"
+
+test format_yang {} {
+ ly_cmd "-f yang $mdir/modleaf.yang" "leaf lfl"
+} {}
+
+test format_yang_submodule {Print submodule in yang format} {
+ ly_cmd "-s modsub -f yang $mdir/modinclude.yang" "submodule modsub"
+} {}
+
+test format_yin {} {
+ ly_cmd "-f yin $mdir/modleaf.yang" "<leaf name=\"lfl\">"
+} {}
+
+test format_yin_submodule {Print submodule in yin format} {
+ ly_cmd "-s modsub -f yin $mdir/modinclude.yang" "<submodule name=\"modsub\""
+} {}
+
+test format_info {} {
+ ly_cmd "-f info $mdir/modleaf.yang" "status current"
+} {}
+
+test format_tree {} {
+ ly_cmd "-f tree $mdir/modleaf.yang" "\\+--rw lfl"
+} {}
+
+test format_data_xml {Print data in xml format} {
+ ly_cmd "-f xml $mdir/modleaf.yang $ddir/modleaf.xml" "<lfl xmlns=\"urn:yanglint:modleaf\">7</lfl>"
+} {}
+
+test format_data_json {Print data in json format} {
+ ly_cmd "-f json $mdir/modleaf.yang $ddir/modleaf.xml" "{\n \"modleaf:lfl\": 7\n}"
+} {}
+
+test format_data_lyb_err {Printing in LYB format: expect error due to missing parameter} {
+ ly_cmd_err "-f lyb $mdir/modleaf.yang $ddir/modleaf.xml" "The LYB format requires the -o"
+} {}
+
+test format_tree_submodule {Print submodule in tree format} {
+ ly_cmd "-s modsub -f tree $mdir/modinclude.yang" "submodule: modsub"
+} {}
+
+test format_tree_path {Print subtree in tree format} {
+ ly_cmd "-f tree -P $ipv6_path $mdir/ietf-ip.yang" "\\+--rw address.*\\+--rw prefix-length"
+} {}
+
+test format_tree_path_single_node {Print node in tree format} {
+ ly_cmd "-f tree -q -P $ipv6_path $mdir/ietf-ip.yang" "\\+--rw address\\* \\\[ip\\\]$"
+} {}
+
+test format_tree_path_single_node_line_length {Print node in the tree format and limit row size} {
+ ly_cmd "-f tree -L 20 -q -P $ipv6_path $mdir/ietf-ip.yang" "\\+--rw address\\*\n *\\\[ip\\\]$"
+} {}
+
+test format_feature_param_one_module {Show features for one module} {
+ ly_cmd "-f feature-param $mdir/ietf-ip.yang" " -F ietf-ip:ipv4-non-contiguous-netmasks,ipv6-privacy-autoconf" -ex
+} {}
+
+test format_feature_param_more_modules {Show a mix of modules with and without features} {
+
+ set features " -F modfeature:ftr1,ftr2\
+-F modleaf:\
+-F ietf-ip:ipv4-non-contiguous-netmasks,ipv6-privacy-autoconf"
+
+ ly_cmd "-f feature-param $mdir/modfeature.yang $mdir/modleaf.yang $mdir/ietf-ip.yang" $features -ex
+} {}
+
+cleanupTests
diff --git a/tests/yanglint/non-interactive/list.test b/tests/yanglint/non-interactive/list.test
new file mode 100644
index 0000000..626d9a1
--- /dev/null
+++ b/tests/yanglint/non-interactive/list.test
@@ -0,0 +1,26 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/non-interactive/ly.tcl" : "ly.tcl"}]
+namespace import uti::regex_xml_elements uti::regex_json_pairs
+
+set modules {ietf-yang-library ietf-inet-types}
+
+test list_basic {} {
+ ly_cmd "-l" "ietf-yang-types"
+} {}
+
+test list_format_xml {list --format xml} {
+ ly_cmd "-y -f xml -l" [regex_xml_elements $modules "name"]
+} {}
+
+test list_format_json {list --format json} {
+ ly_cmd "-y -f json -l" [regex_json_pairs $modules "name"]
+} {}
+
+test list_ietf_yang_library {Error due to missing ietf-yang-library} {
+ ly_cmd_err "-f xml -l" "Module \"ietf-yang-library\" is not implemented."
+} {}
+
+test list_bad_format {Error due to bad format} {
+ ly_cmd_err "-f csv -l" "Unknown output format csv"
+} {}
+
+cleanupTests
diff --git a/tests/yanglint/non-interactive/ly.tcl b/tests/yanglint/non-interactive/ly.tcl
new file mode 100644
index 0000000..f6bb2c7
--- /dev/null
+++ b/tests/yanglint/non-interactive/ly.tcl
@@ -0,0 +1,8 @@
+# @brief The main source of functions and variables for testing yanglint in the non-interactive mode.
+
+# For testing yanglint.
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/common.tcl" : "../common.tcl"}]
+# For testing any non-interactive tool.
+source "$::env(TESTS_DIR)/../tool_ni.tcl"
+
+# The script continues by defining variables and functions specific to the non-interactive yanglint tool.
diff --git a/tests/yanglint/non-interactive/make_implemented.test b/tests/yanglint/non-interactive/make_implemented.test
new file mode 100644
index 0000000..40cead9
--- /dev/null
+++ b/tests/yanglint/non-interactive/make_implemented.test
@@ -0,0 +1,17 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/non-interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir $::env(YANG_MODULES_DIR)
+
+test make_impl_no_set {Import while --make-implemented is not set} {
+ ly_cmd "-l $mdir/modleafref.yang" "I modleafref\n.*I modleaf"
+} {}
+
+test make_impl_set_once {--make-implemented} {
+ ly_cmd "-l -i $mdir/modmust.yang" "I modmust\n.*I modleaf"
+} {}
+
+test make_impl_set_twice {-i -i} {
+ ly_cmd "-l -i -i $mdir/modimp-type.yang" "I modimp-type\n.*I modtypedef"
+} {}
+
+cleanupTests
diff --git a/tests/yanglint/non-interactive/modcwd.yang b/tests/yanglint/non-interactive/modcwd.yang
new file mode 100644
index 0000000..db33e73
--- /dev/null
+++ b/tests/yanglint/non-interactive/modcwd.yang
@@ -0,0 +1,4 @@
+module modcwd {
+ namespace "urn:yanglint:modcwd";
+ prefix mc;
+}
diff --git a/tests/yanglint/non-interactive/path.test b/tests/yanglint/non-interactive/path.test
new file mode 100644
index 0000000..bf915ff
--- /dev/null
+++ b/tests/yanglint/non-interactive/path.test
@@ -0,0 +1,9 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/non-interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir $env(YANG_MODULES_DIR)
+
+test path_basic {} {
+ ly_cmd "-p $::env(TESTS_DIR)/data $::env(YANG_MODULES_DIR)/modimp-path.yang"
+} {}
+
+cleanupTests
diff --git a/tests/yanglint/non-interactive/yang_library_file.test b/tests/yanglint/non-interactive/yang_library_file.test
new file mode 100644
index 0000000..bd95978
--- /dev/null
+++ b/tests/yanglint/non-interactive/yang_library_file.test
@@ -0,0 +1,18 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/non-interactive/ly.tcl" : "ly.tcl"}]
+
+set mdir "$::env(YANG_MODULES_DIR)"
+set ddir "$::env(TESTS_DIR)/data"
+
+test ylf_list {apply --yang-library-file and check result by --list} {
+ ly_cmd "-Y $ddir/modimp_type_ctx.xml -p $mdir -l" "I modimp-type.*i modtypedef"
+} {}
+
+test ylf_make_implemented {apply --yang-library-file and --make-implemented} {
+ ly_cmd "-Y $ddir/modimp_type_ctx.xml -p $mdir -i -i -l" "I modimp-type.*I modtypedef"
+} {}
+
+test ylf_augment_ctx {Setup context by yang-library-file and augment module} {
+ ly_cmd "-Y $ddir/modconfig_ctx.xml -p $mdir -f tree $mdir/modconfig.yang $mdir/modconfig-augment.yang" "mca:alf"
+} {}
+
+cleanupTests
diff --git a/tests/yangre/CMakeLists.txt b/tests/yangre/CMakeLists.txt
new file mode 100644
index 0000000..ce5b39b
--- /dev/null
+++ b/tests/yangre/CMakeLists.txt
@@ -0,0 +1,8 @@
+find_program(PATH_TCLSH NAMES tclsh)
+if(NOT PATH_TCLSH)
+ message(WARNING "'tclsh' not found! The yangre test will not be available.")
+else()
+ add_test(NAME "yangre" COMMAND "tclsh" "${CMAKE_CURRENT_SOURCE_DIR}/all.tcl")
+ set_property(TEST "yangre" APPEND PROPERTY ENVIRONMENT "TESTS_DIR=${CMAKE_CURRENT_SOURCE_DIR}")
+ set_property(TEST "yangre" APPEND PROPERTY ENVIRONMENT "YANGRE=${PROJECT_BINARY_DIR}")
+endif()
diff --git a/tests/yangre/all.tcl b/tests/yangre/all.tcl
new file mode 100644
index 0000000..f00563f
--- /dev/null
+++ b/tests/yangre/all.tcl
@@ -0,0 +1,15 @@
+package require tcltest
+
+# Hook to determine if any of the tests failed.
+# Sets a global variable exitCode to 1 if any test fails otherwise it is set to 0.
+proc tcltest::cleanupTestsHook {} {
+ variable numTests
+ set ::exitCode [expr {$numTests(Failed) > 0}]
+}
+
+if {[info exists ::env(TESTS_DIR)]} {
+ tcltest::configure -testdir "$env(TESTS_DIR)"
+}
+
+tcltest::runAllTests
+exit $exitCode
diff --git a/tests/yangre/arg.test b/tests/yangre/arg.test
new file mode 100644
index 0000000..821aad1
--- /dev/null
+++ b/tests/yangre/arg.test
@@ -0,0 +1,19 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/ly.tcl" : "ly.tcl"}]
+
+test arg_empty {Missing arguments} {
+ ly_cmd_err "" "missing <string> parameter to process"
+} {}
+
+test arg_wrong {Wrong argument} {
+ ly_cmd_err "-j" "invalid option"
+} {}
+
+test arg_help {Print help} {
+ ly_cmd "-h" "Usage:"
+} {}
+
+test arg_version {Print version} {
+ ly_cmd "-v" "yangre"
+} {}
+
+cleanupTests
diff --git a/tests/yangre/file.test b/tests/yangre/file.test
new file mode 100644
index 0000000..80ea3f6
--- /dev/null
+++ b/tests/yangre/file.test
@@ -0,0 +1,37 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/ly.tcl" : "ly.tcl"}]
+
+set fdir "$::env(TESTS_DIR)/files"
+
+test file_empty {file is empty} {
+ ly_cmd "-f $fdir/empty.txt"
+} {}
+
+test file_empty_str {<string> is empty} {
+ ly_cmd "-f $fdir/empty_str.txt"
+} {}
+
+test file_empty_str_err {empty <string> is not allowed} {
+ ly_cmd_err "-f $fdir/empty_str_err.txt" "does not conform"
+} {}
+
+test file_one_pattern {one pattern in the file} {
+ ly_cmd "-f $fdir/one_pattern.txt"
+} {}
+
+test file_two_patterns {two patterns in the file} {
+ ly_cmd "-f $fdir/two_patterns.txt"
+} {}
+
+test file_two_patterns_err {two patterns and the <string> is wrong} {
+ ly_cmd_err "-f $fdir/two_patterns_err.txt" "does not conform"
+} {}
+
+test file_two_patterns_invert_match {one pattern is inverted} {
+ ly_cmd "-f $fdir/two_patterns_invert_match.txt"
+} {}
+
+test file_two_patterns_invert_match_err {one pattern is inverted and the <string> is wrong} {
+ ly_cmd_err "-f $fdir/two_patterns_invert_match_err.txt" "does not conform to inverted"
+} {}
+
+cleanupTests
diff --git a/tests/yangre/files/empty.txt b/tests/yangre/files/empty.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/yangre/files/empty.txt
diff --git a/tests/yangre/files/empty_str.txt b/tests/yangre/files/empty_str.txt
new file mode 100644
index 0000000..bf9b1b5
--- /dev/null
+++ b/tests/yangre/files/empty_str.txt
@@ -0,0 +1,2 @@
+"[0-9a-fA-F]*"
+
diff --git a/tests/yangre/files/empty_str_err.txt b/tests/yangre/files/empty_str_err.txt
new file mode 100644
index 0000000..f48a15d
--- /dev/null
+++ b/tests/yangre/files/empty_str_err.txt
@@ -0,0 +1,2 @@
+"[0-9a-fA-F]+"
+
diff --git a/tests/yangre/files/one_pattern.txt b/tests/yangre/files/one_pattern.txt
new file mode 100644
index 0000000..cf9acc5
--- /dev/null
+++ b/tests/yangre/files/one_pattern.txt
@@ -0,0 +1,3 @@
+"[0-9a-fA-F]*"
+
+1F
diff --git a/tests/yangre/files/two_patterns.txt b/tests/yangre/files/two_patterns.txt
new file mode 100644
index 0000000..7d04b2c
--- /dev/null
+++ b/tests/yangre/files/two_patterns.txt
@@ -0,0 +1,4 @@
+"[0-9a-fA-F]*"
+'[a-zA-Z0-9\-_.]*'
+
+1F
diff --git a/tests/yangre/files/two_patterns_err.txt b/tests/yangre/files/two_patterns_err.txt
new file mode 100644
index 0000000..78f9878
--- /dev/null
+++ b/tests/yangre/files/two_patterns_err.txt
@@ -0,0 +1,4 @@
+"[0-9a-fA-F]*"
+'[a-zA-Z0-9\-_.]*'
+
+@!@
diff --git a/tests/yangre/files/two_patterns_invert_match.txt b/tests/yangre/files/two_patterns_invert_match.txt
new file mode 100644
index 0000000..ffbd835
--- /dev/null
+++ b/tests/yangre/files/two_patterns_invert_match.txt
@@ -0,0 +1,4 @@
+"[a-z]*"
+ '[a-f]*'
+
+gh
diff --git a/tests/yangre/files/two_patterns_invert_match_err.txt b/tests/yangre/files/two_patterns_invert_match_err.txt
new file mode 100644
index 0000000..f182aab
--- /dev/null
+++ b/tests/yangre/files/two_patterns_invert_match_err.txt
@@ -0,0 +1,4 @@
+"[a-z]*"
+ '[a-f]*'
+
+ab
diff --git a/tests/yangre/invert_match.test b/tests/yangre/invert_match.test
new file mode 100644
index 0000000..707ca9d
--- /dev/null
+++ b/tests/yangre/invert_match.test
@@ -0,0 +1,28 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/ly.tcl" : "ly.tcl"}]
+
+test invert_match_from_help1 {Test the first pattern from help via invert match} {
+ ly_cmd_err {-p {"[0-9a-fA-F]*"} -i {1F}} "not conform to inverted"
+ ly_cmd {-p {"[0-9a-fA-F]*"} -i {GUN}}
+} {}
+
+test invert_match_from_help2 {Test the second pattern from help via invert match} {
+ ly_cmd_err {-p {'[a-zA-Z0-9\-_.]*'} -i {a-b}} "not conform to inverted"
+ ly_cmd {-p {'[a-zA-Z0-9\-_.]*'} -i {%@}}
+} {}
+
+test invert_match_from_help3 {Test the third pattern from help via invert match} {
+ ly_cmd_err {-p {[xX][mM][lL].*} -i {xml-encoding}} "not conform to inverted"
+ ly_cmd {-p {[xX][mM][lL].*} -i {json}}
+} {}
+
+test invert_match_three_at_once {Test three inverted patterns and once} {
+ ly_cmd_err {-p {"[0-9a-zA-Z]*"} -i -p {'[a-zA-Z0-9\-_.]*'} -i -p {[xX][mM][lL].*} -i {xml}} "not conform to inverted"
+ ly_cmd {-p {"[0-9a-zA-Z]*"} -i -p {'[a-zA-Z0-9\-_.]*'} -i -p {[xX][mM][lL].*} -i {%@}}
+} {}
+
+test invert_match_second_is_not {Test three patterns but the second one is not inverted} {
+ ly_cmd_err {-p {"[0-9a-zA-Z]*"} -i -p {'[a-zA-Z0-9\-_.]*'} -i -p {[xX][mM][lL].*} -i {o_O}} "not conform to inverted"
+ ly_cmd {-p {"[0-9a-zA-Z]*"} -i -p {'[a-zA-Z0-9\-_.]*'} -p {[xX][mM][lL].*} -i {o_O}}
+} {}
+
+cleanupTests
diff --git a/tests/yangre/ly.tcl b/tests/yangre/ly.tcl
new file mode 100644
index 0000000..3bb62b5
--- /dev/null
+++ b/tests/yangre/ly.tcl
@@ -0,0 +1,17 @@
+# @brief The main source of functions and variables for testing yangre.
+
+package require tcltest
+namespace import ::tcltest::test ::tcltest::cleanupTests
+
+if { ![info exists ::env(TESTS_DIR)] } {
+ # the script is not run via 'ctest' so paths must be set
+ set ::env(TESTS_DIR) "./"
+ set TUT_PATH "../../build"
+} else {
+ # cmake (ctest) already sets ::env variables
+ set TUT_PATH $::env(YANGRE)
+}
+set TUT_NAME "yangre"
+source "$::env(TESTS_DIR)/../tool_ni.tcl"
+
+# The script continues by defining variables and functions specific to the yangre tool.
diff --git a/tests/yangre/pattern.test b/tests/yangre/pattern.test
new file mode 100644
index 0000000..45b7e3b
--- /dev/null
+++ b/tests/yangre/pattern.test
@@ -0,0 +1,19 @@
+source [expr {[info exists ::env(TESTS_DIR)] ? "$env(TESTS_DIR)/ly.tcl" : "ly.tcl"}]
+
+test pattern_from_help1 {Test the first pattern from help} {
+ ly_cmd {-p {"[0-9a-fA-F]*"} {1F}}
+} {}
+
+test pattern_from_help2 {Test the second pattern from help} {
+ ly_cmd {-p {'[a-zA-Z0-9\-_.]*'} {a-b}}
+} {}
+
+test pattern_from_help3 {Test the third pattern from help} {
+ ly_cmd {-p {[xX][mM][lL].*} {xml-encoding}}
+} {}
+
+test pattern_three_at_once {Test three patterns and once} {
+ ly_cmd {-p {"[0-9a-zA-Z]*"} -p {'[a-zA-Z0-9\-_.]*'} -p {[xX][mM][lL].*} {xml}}
+} {}
+
+cleanupTests