yanglint TEST moved to the tests directory
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.*$"
+}