yanglint CHANGE of common testing expect script

New functions were added to common.exp and some changed, this affected
other scripts. Overall, the effort was to make the functions so that
you don't have to use the expect command at all in your test scripts.
New, for example, is the reporting of a line where the output check
has failed.
diff --git a/tools/lint/tests/expect/common.exp b/tools/lint/tests/expect/common.exp
index 0381e6c..eac35a7 100644
--- a/tools/lint/tests/expect/common.exp
+++ b/tools/lint/tests/expect/common.exp
@@ -5,48 +5,108 @@
     set yanglint "../../../../build/yanglint"
 }
 
+# detect the path to the examples
+if { [info exists ::env(CURRENT_SOURCE_DIR)] } {
+    set yang_dir "$env(CURRENT_SOURCE_DIR)/examples"
+} else {
+    set yang_dir "../../examples"
+}
+
+# set the variable used to print the error message
+if { ![info exists error_verbose] } {
+    set error_verbose 1
+}
+
+# prompt of yanglint
+set prompt "> "
+# prompt of error message
+set error_prompt ">>>"
+# the beginning of error message
+set error_head "$error_prompt Check-failed"
 # set the timeout to 1 second
 set timeout 1
 
-# expect a single line of anchored regex output
-proc expect_output {output} {
-    expect {
-        -re "^${output}$" {}
-        timeout {exit 1}
+# detection on eof and timeout will be on every expect command
+expect_after {
+    eof {
+        global error_head
+        send_error "\n$error_head unexpected termination.\n"
+        exit 1
+    } timeout {
+        global error_head
+        send_error "\n$error_head timeout.\n"
+        exit 1
     }
 }
 
-# send a command and either expect some anchored regex output if specified or just an empty line
-proc expect_command {command has_output output} {
-    send -- "${command}\r"
+# Internal function. Print error message and exit script with an error return value.
+proc check_failed {pattern output} {
+    global error_verbose
+    global error_prompt
+    global error_head
 
-    if ($has_output==1) {
-        expect {
-            -re "^${command}\r\n${output}$" {}
-            timeout {exit 1}
+    set frame [info frame 1]
+    set line [dict get $frame line]
+    set file [lindex [split [dict get $frame file] /] end]
+    switch $error_verbose {
+        0 {}
+        1 { send_error "\n$error_head in $file on line $line\n" }
+        2 { send_error "\n$error_head in $file on line $line, output is:\n$output\n" }
+        3 {
+            send_error "\n$error_head in $file on line $line, expecting:\n$pattern\n"
+            send_error "$error_prompt but the output is:\n$output\n"
         }
-    } else {
-        # input echoes
-        expect {
-            -re "^${command}\r\n$" {}
-            timeout {exit 1}
-        }
-        expect {
-            -re "^> $" {}
-            timeout {exit 1}
+        default { send_error "\n$error_head unrecognized entry \"$error_verbose\" in error_verbose variable.\n" }
+    }
+    close
+    wait
+    exit 1
+}
+
+# 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 ""}} {
+    global prompt
+
+    send -- "${cmd}\r"
+    expect "${cmd}\r\n"
+
+    if { $pattern eq "" } {
+        # command without output
+        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)
         }
     }
 }
 
+# whatever is written is sent, output is ignored and then another prompt is expected
+proc next_prompt {} {
+    global prompt
+
+    send "\r"
+    expect -re "$prompt$"
+}
+
 # send a completion request and check if the anchored regex output matches
 proc expect_completion {input output} {
-    send -- "${input}\t"
+    global prompt
 
-    expect {
-        # expecting echoing input, output and 10 terminal control characters
-        -re "^${input}\r> ${output}.*\r.*$" {}
-        timeout {exit 1}
-    }
+    send -- "${input}\t"
+    # expecting echoing input, output and 10 terminal control characters
+    expect -re "^${input}\r> ${output}.*\r.*$"
 }
 
 # send a completion request and check if the anchored regex hint options match
@@ -58,11 +118,13 @@
     }
 
     send -- "${input}\t"
+    # expecting the hints, previous input from which the hints were generated
+    # and some number of terminal control characters
+    expect -re "^\r\n${output}\r> ${prev_input}.*\r.*$"
+}
 
-    expect {
-        # expecting the hints, previous input from which the hints were generated
-        # and some number of terminal control characters
-        -re "^\r\n${output}\r> ${prev_input}.*\r.*$" {}
-        timeout {exit 1}
-    }
+# send 'exit' and wait for eof
+proc send_exit {} {
+    send "exit\r"
+    expect eof
 }
diff --git a/tools/lint/tests/expect/completion.exp b/tools/lint/tests/expect/completion.exp
index ed4f6bd..119b7e4 100755
--- a/tools/lint/tests/expect/completion.exp
+++ b/tools/lint/tests/expect/completion.exp
@@ -1,30 +1,19 @@
 #!/usr/bin/expect -f
 
-if { [info exists ::env(CURRENT_SOURCE_DIR)] } {
-    source "$env(CURRENT_SOURCE_DIR)/tests/expect/common.exp"
-    set yang_dir "$env(CURRENT_SOURCE_DIR)/examples"
-} else {
-    source "common.exp"
-    set yang_dir "../../examples"
-}
+source [expr {[info exists ::env(CURRENT_SOURCE_DIR)] ? "$env(CURRENT_SOURCE_DIR)/tests/expect/common.exp" : "common.exp"}]
 
 spawn $yanglint
+skip_warnings
 
-# skip no dir and/or no history warnings
-expect_output "(YANGLINT.*)*> "
-
-expect_command "clear -ii" 0 ""
-
-expect_command "add ${yang_dir}/ietf-ip.yang" 0 ""
+command "clear -ii"
+command "add ${yang_dir}/ietf-ip.yang"
 
 expect_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"}
-
 expect_hint "" "print -f info -P /ietf-" $hints
 
 expect_completion "i" "print -f info -P /ietf-interfaces:interfaces"
-
 expect_completion "/" "print -f info -P /ietf-interfaces:interfaces/interface"
 
 set hints {"/ietf-interfaces:interfaces/interface"
@@ -32,29 +21,18 @@
 "/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"}
-
 expect_hint "" "print -f info -P /ietf-interfaces:interfaces/interface" $hints
 
 expect_completion "/i" "print -f info -P /ietf-interfaces:interfaces/interface/ietf-ip:ipv"
-
 expect_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"
 }
-
 expect_hint "\t" "print -f info -P /ietf-interfaces:interfaces/interface/ietf-ip:ipv" $hints
 
 expect_completion "/e" "print -f info -P /ietf-interfaces:interfaces/interface/ietf-ip:ipv4/enabled "
 
-send -- "\r"
-
-expect {
-    -re ".*\r\n> " {}
-    timeout {exit 1}
-}
-
-send -- "exit\r"
-
-expect eof
+next_prompt
+send_exit
diff --git a/tools/lint/tests/expect/feature.exp b/tools/lint/tests/expect/feature.exp
index 37680b0..c499bf9 100755
--- a/tools/lint/tests/expect/feature.exp
+++ b/tools/lint/tests/expect/feature.exp
@@ -1,20 +1,10 @@
 #!/usr/bin/expect -f
 
-if { [info exists ::env(CURRENT_SOURCE_DIR)] } {
-    source "$env(CURRENT_SOURCE_DIR)/tests/expect/common.exp"
-    set yang_dir "$env(CURRENT_SOURCE_DIR)/examples"
-} else {
-    source "common.exp"
-    set yang_dir "../../examples"
-}
+source [expr {[info exists ::env(CURRENT_SOURCE_DIR)] ? "$env(CURRENT_SOURCE_DIR)/tests/expect/common.exp" : "common.exp"}]
 
 spawn $yanglint
+skip_warnings
 
-# skip no dir and/or no history warnings
-expect_output "(YANGLINT.*)*> "
+command "feature -a" "yang:\r\n\t\\(none\\)\r\n\r\nietf-yang-schema-mount:\r\n\t\\(none\\)\r\n"
 
-expect_command "feature -a" 1 "yang:\r\n\t\\(none\\)\r\n\r\nietf-yang-schema-mount:\r\n\t\\(none\\)\r\n\r\n> "
-
-send -- "exit\r"
-
-expect eof
+send_exit
diff --git a/tools/lint/tests/expect/list.exp b/tools/lint/tests/expect/list.exp
index ec3cdba..3d74c1a 100755
--- a/tools/lint/tests/expect/list.exp
+++ b/tools/lint/tests/expect/list.exp
@@ -1,20 +1,10 @@
 #!/usr/bin/expect -f
 
-if { [info exists ::env(CURRENT_SOURCE_DIR)] } {
-    source "$env(CURRENT_SOURCE_DIR)/tests/expect/common.exp"
-    set yang_dir "$env(CURRENT_SOURCE_DIR)/examples"
-} else {
-    source "common.exp"
-    set yang_dir "../../examples"
-}
+source [expr {[info exists ::env(CURRENT_SOURCE_DIR)] ? "$env(CURRENT_SOURCE_DIR)/tests/expect/common.exp" : "common.exp"}]
 
 spawn $yanglint
+skip_warnings
 
-# skip no dir and/or no history warnings
-expect_output "(YANGLINT.*)*> "
+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"
 
-expect_command "list" 1 "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\r\n> "
-
-send -- "exit\r"
-
-expect eof
+send_exit