blob: dea0c3fc10d9f8ccfcb2c468bb5fe6a1a6a35c35 [file] [log] [blame]
# detect the path to the yanglint binary
if { [info exists ::env(YANGLINT)] } {
set yanglint "$env(YANGLINT)"
} else {
set yanglint "../../../../build/yanglint"
}
# detect the path to the examples
if { [info exists ::env(CURRENT_SOURCE_DIR)] } {
set yang_models "$env(CURRENT_SOURCE_DIR)/tests/models"
} else {
set yang_models "../models"
}
# 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
# 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
}
}
# 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
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"
}
default { send_error "\n$error_head unrecognized entry \"$error_verbose\" in error_verbose variable.\n" }
}
close
wait
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 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"
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 "" } {
# 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
}
}
# 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} {
global prompt
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
proc expect_hint {input prev_input hints} {
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 "^\r\n${output}\r> ${prev_input}.*\r.*$"
}
# send 'exit' and wait for eof
proc send_exit {} {
send "exit\r"
expect eof
}