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