yanglint TEST more checks added to list.exp
Also new functions added to common.exp.
diff --git a/tools/lint/tests/expect/common.exp b/tools/lint/tests/expect/common.exp
index d73ff15..dea0c3f 100644
--- a/tools/lint/tests/expect/common.exp
+++ b/tools/lint/tests/expect/common.exp
@@ -63,15 +63,98 @@
exit 1
}
+# 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 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 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 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 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 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 regex_xml_contains_elements {values tag} {
+ return [list_to_regex [wrap_list_items $values "<$tag>" "</$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 regex_json_contains_pairs {values attribute} {
+ return [list_to_regex [wrap_list_items $values "\"$attribute\": \"" "\""]]
+}
+
# skip no dir and/or no history warnings and prompt
proc skip_warnings {} {
global prompt
expect -re "(YANGLINT.*)*$prompt" {}
}
-# Send command (cmd) to the yanglint, then check output string (pattern) and prompt.
-# If parameter pattern is not specified, only the prompt assumed afterwards.
-proc command {cmd {pattern ""}} {
+# Send command 'cmd' to the process, then check output string by 'pattern'.
+# The parameter 'pattern' should not contain prompt.
+# If 'pattern' is not specified, only the prompt assumed afterwards.
+# 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 command {cmd {pattern ""} {opt ""}} {
global prompt
send -- "${cmd}\r"
@@ -82,13 +165,32 @@
expect $prompt
return
}
- # check output
- expect {
- -re "^${pattern}\r\n${prompt}$" {}
- -indices -re "(.*)\r\n${prompt}$" {
- # Pattern does not match the output. Print error and exit the script.
- check_failed $pattern $expect_out(1,string)
+
+ # definition of an expression that matches failure
+ set failure_pattern "(.*)\r\n${prompt}$"
+
+ if { $opt eq "" } {
+ # check output by regular expression
+ expect {
+ -re "^${pattern}\r\n${prompt}$" {}
+ -indices -re $failure_pattern {
+ # Pattern does not match the output. Print error and exit the script.
+ check_failed $pattern $expect_out(1,string)
+ }
}
+ } elseif { $opt eq "-ex" } {
+ # check output by exact matching
+ expect {
+ -ex "${pattern}\r\n${prompt}" {}
+ -indices -re $failure_pattern {
+ # Pattern does not match the output. Print error and exit the script.
+ check_failed $pattern $expect_out(1,string)
+ }
+ }
+ } else {
+ global error_head
+ send_error "\n$error_head unrecognized value of parameter 'opt'.\n"
+ exit 1
}
}
diff --git a/tools/lint/tests/expect/feature.exp b/tools/lint/tests/expect/feature.exp
index c499bf9..4c77436 100755
--- a/tools/lint/tests/expect/feature.exp
+++ b/tools/lint/tests/expect/feature.exp
@@ -5,6 +5,6 @@
spawn $yanglint
skip_warnings
-command "feature -a" "yang:\r\n\t\\(none\\)\r\n\r\nietf-yang-schema-mount:\r\n\t\\(none\\)\r\n"
+command "feature -a" "yang:\r\n\t(none)\r\n\r\nietf-yang-schema-mount:\r\n\t(none)\r\n" -ex
send_exit
diff --git a/tools/lint/tests/expect/list.exp b/tools/lint/tests/expect/list.exp
index 3d74c1a..0d4b2ce 100755
--- a/tools/lint/tests/expect/list.exp
+++ b/tools/lint/tests/expect/list.exp
@@ -5,6 +5,52 @@
spawn $yanglint
skip_warnings
-command "list" "List of the loaded models:\r\n *i ietf-yang-metadata@2016-08-05\r\n *I yang@2022-06-16\r\n *i ietf-inet-types@2013-07-15\r\n *i ietf-yang-types@2013-07-15\r\n *I ietf-yang-schema-mount@2019-01-14\r\n *i ietf-yang-structure-ext@2020-06-17"
+# default loaded models
+command "list" "List of the loaded models:\r
+ i ietf-yang-metadata@2016-08-05\r
+ I yang@2022-06-16\r
+ i ietf-inet-types@2013-07-15\r
+ i ietf-yang-types@2013-07-15\r
+ I ietf-yang-schema-mount@2019-01-14\r
+ i ietf-yang-structure-ext@2020-06-17" -ex
+
+# add models for ietf-yang-library
+command "clear -y"
+
+# check that the new models has been added
+command "list" "List of the loaded models:\r
+ i ietf-yang-metadata@2016-08-05\r
+ I yang@2022-06-16\r
+ i ietf-inet-types@2013-07-15\r
+ i ietf-yang-types@2013-07-15\r
+ I ietf-yang-schema-mount@2019-01-14\r
+ i ietf-yang-structure-ext@2020-06-17\r
+ I ietf-datastores@2018-02-14\r
+ I ietf-yang-library@2019-01-04" -ex
+
+# list --format
+# print xml format
+set modules {complete yang ietf-yang-schema-mount
+ ietf-datastores ietf-yang-library ietf-yang-metadata
+ ietf-inet-types ietf-yang-types ietf-yang-structure-ext
+}
+command "list -f xml" [list_to_regex [wrap_to_xml $modules "name"]]
+# print json format
+command "list -f json" [list_to_regex [wrap_to_json $modules "name"]]
+
+# remove all the loaded modules
+command "clear"
+command "list" "List of the loaded models:\r
+ i ietf-yang-metadata@2016-08-05\r
+ I yang@2022-06-16\r
+ i ietf-inet-types@2013-07-15\r
+ i ietf-yang-types@2013-07-15\r
+ I ietf-yang-schema-mount@2019-01-14\r
+ i ietf-yang-structure-ext@2020-06-17" -ex
+
+# error message when using --format without ietf-yang-library
+command "list -f xml" "libyang\[0\]: Module \"ietf-yang-library\" is not implemented.\r
+YANGLINT\[E\]: Getting context info (ietf-yang-library data) failed.\
+If the YANG module is missing or not implemented, use an option to add it internally." -ex
send_exit