TCL/Expect-在期望时输出未显示在缓冲区中
好的,我在一家电信公司工作,我为该公司开发了一些针对我们产品的自动化测试。我正在使用TCL8.4和Expect 5.44.1.15,这是我被录用时被要求的。大多数测试包括使用telnet与产品外壳交互。因此,我提出了以下函数:TCL/Expect-在期望时输出未显示在缓冲区中,tcl,buffer,expect,Tcl,Buffer,Expect,好的,我在一家电信公司工作,我为该公司开发了一些针对我们产品的自动化测试。我正在使用TCL8.4和Expect 5.44.1.15,这是我被录用时被要求的。大多数测试包括使用telnet与产品外壳交互。因此,我提出了以下函数: # ------------------------------------------------------------------------------ # Description: Launch telnet session with specified
# ------------------------------------------------------------------------------
# Description: Launch telnet session with specified IP and port and assign
# resulting spawned process ID to processIDRef upon success.
#
# Parameters: ipAddr - in: IPv4 address to connect with.
# port - in: Port number to connect with.
# prompt - in: String indicating a successfull connection.
# processIDRef - out: Resulting spawned process identifier.
#
# Return: Returns no significant value. Throws exception on failure.
# ------------------------------------------------------------------------------
proc ::connections::telnet::Connect {ipAddr port prompt processIDRef} {
# Print function name and parameters
::utils::PrintDebug [info level 0]
# Parameter reference(s)
upvar $processIDRef processID
# Validate parameters
if {![regexp -- {^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}} $ipAddr]} {
::utils::Throw "Unsupported IP addresse format/value: \"$ipAddr\""
} elseif {[string length $port] && !([string is integer $port] && $port >= 0)} {
::utils::Throw "Unsupported port number format/value: \"$port\""
}
# Spawn telnet session and expect prompt.
if {![string length $port]} {
# passing an empty string as port argument to telnet causes an error
spawn telnet $ipAddr
} else {
spawn telnet $ipAddr $port
}
AddActiveSession $spawn_id
Expect $spawn_id $prompt 30
set processID $spawn_id
}
# ------------------------------------------------------------------------------
# Description: Close telnet session associated with processID.
#
# Parameters: processID - in: Spawned process identifier.
#
# Return: Returns no significant value. Throws exception on failure.
# ------------------------------------------------------------------------------
proc ::connections::telnet::Disconnect {processID} {
# Print function name and parameters
::utils::PrintDebug [info level 0]
# Validate parameters
if {![IsActiveSession $processID]} {
::utils::Throw "Unknown/Invalid processID: \"$processID\""
}
if {[::utils::IsProcessAlive $processID]} {
# Open Telnet Prompt
SendCommand $processID "\x1D" "" "telnet> " 10
# Close telnet session
SendCommand $processID "close" {\n} "Connection closed." 10
# Remove from active sessions and close expect connection
RemoveActiveSession $processID
wait -i $processID
close -i $processID
} else {
# Process is dead.
RemoveActiveSession $processID
}
}
# ------------------------------------------------------------------------------
# Description: Send command to process and expect response within alloted time.
# Response can be collected inside a buffer if provided a reference.
#
# Parameters: processID - in: Spawnded process identifier.
# command - in: String to be sent to process.
# terminator - in: Character to append to command, signaling the
# end of the command string for the interpreter.
# prompt - in: Regular Expression indicating end of command
# execution.
# timelimit - in: amount time we expect results before declaring
# failed execution.
# bufferRef - out: Resulting command execution output.
#
# Return: 1 if prompt was found within the timelimit, otherwise
# throws an exception.
# ------------------------------------------------------------------------------
proc ::connections::telnet::SendCommand {processID command terminator prompt timelimit {bufferRef ""}} {
# Print function name and parameters
::utils::PrintDebug [info level 0]
# Parameter reference(s)
if {[string length $bufferRef]} {
upvar $bufferRef buffer
}
set buffer ""
# Set expect parameters
set spawn_id $processID
# Send command and expect results
send -s "$command[subst $terminator]"
Expect $processID $prompt $timelimit buffer
}
# ------------------------------------------------------------------------------
# Description: Expect response within alloted time.
# Response can be collected inside a buffer if provided a reference.
#
# Parameters: processID - in: Spawnded process identifier.
# prompt - in: Regular Expression indicating end of command
# execution.
# timelimit - in: amount time we expect results before declaring
# failed execution.
# bufferRef - out: Resulting command execution output.
#
# Return: Returns no significant value. Throws exception on failure.
# ------------------------------------------------------------------------------
proc ::connections::telnet::Expect {processID prompt timelimit {bufferRef ""}} {
# Print function name and parameters
::utils::PrintDebug [info level 0]
# Parameter reference(s)
if {[string length $bufferRef]} {
upvar $bufferRef buffer
}
set buffer ""
# Validate parameters
if {![IsActiveSession $processID]} {
::utils::Throw "Unknown/Invalid processID: \"$processID\""
} elseif {!([string is integer $timelimit] && $timelimit >= 0)} {
::utils::Throw "Unsupported timeout format/value: \"$timelimit\""
}
# Set expect parameters
set spawn_id $processID
set timeout $timelimit
# expect results
expect {
-re "$prompt" {
# Command Successful
if {[info exists expect_out(buffer)]} {
append buffer $expect_out(buffer)
}
# Print Buffer to log file at least
::utils::PrintDebug $buffer
}
full_buffer {
# expect_out(buffer) is full
if {[string length $bufferRef]} {
append buffer $expect_out(buffer)
}
exp_continue
}
timeout {
# Timeout
if {[info exists expect_out(buffer)]} {
append buffer $expect_out(buffer)
}
# Print Buffer to log file at least
::utils::PrintDebug $buffer
# Throw exception
::utils::Throw "Timed out while waiting for \"$prompt\"."
}
eof {
# Process reached it's end
if {[string length $bufferRef] && [info exists expect_out(buffer)]} {
append buffer $expect_out(buffer)
}
# Print Buffer to log file at least
::utils::PrintDebug $buffer
# Throw exception
::utils::Throw "Reached eof while waiting for \"$prompt\"."
}
}
}
基本上,您可以使用以下功能:
- ::连接::telnet::连接
- 使用telnet连接到IP和端口,并期望出现特定提示
- ::连接::telnet::断开连接
- 关闭telnet
- ::连接::telnet::send命令
- 通过telnet发送命令并期望在分配的时间内得到某个提示
- ::连接::telnet::预期
- 在不发送命令的情况下,在分配的时间内预期某个提示
RST_GATE_INITIAL OPEN
HardwareSettleCompleteGate OPEN
HsiAvailableGate CLOSED
DiagnosticsAvailableGate CLOSED
FirmwareReadyGate CLOSED
CardCommsDriverReadyGate CLOSED
ShelfCommsAvailableGate CLOSED
DataProvisioningCompletedGate已关闭
命令于2003年1月7日星期二完成-23:53:38(UTC)
----/重新启动>~*
连接被外部主机关闭
当我尝试新功能时,这种情况可能会持续发生,也可能在我现有的任何功能中间歇性发生。我上面发送的命令在触发此bug之前的几分钟内已经运行了10多次
这给我和我的同事以及使用我的软件包的客户带来了很多麻烦。我们有数以万计的代码行在使用它,随着越来越多的客户使用我们的测试套件,这个问题变得越来越明显。用另一种语言重新书写是我们最后的选择
解决方法:
所以我试着增加超时时间,但这根本不起作用
我也试着连续两次期待(如果第一次期待超时),但即使在两次之间有延迟也没有帮助。就像我必须在再次调用之前离开调用::connections::telnet::Expect的函数一样
我开发了一个函数来清除程序通道缓冲区和expect的缓冲区(因为expect库中似乎还没有包含缓冲区)。有时有帮助,有时没有。即使它在100%的时间内都有帮助,但在每次调用send命令时使用它也不是一个可行的选择,因为它会将每个命令的执行速度降低到至少1秒。这是:
# ------------------------------------------------------------------------------
# Description: Clears a process's channel buffer and expect_out(buffer).
#
# Parameters: processID - in: Spawned process identifier.
#
# Return: void - returns no signicant value.
# ------------------------------------------------------------------------------
proc ::utils::ClearBuffer {processID} {
# Print function name and parameters
PrintDebug [info level 0]
# set expect parameters
set spawn_id $processID
set timeout 1
catch {expect -re "thischainwillmostcertainlyneverappear"}
catch {expect -re ".*"}
}
我的请求:
还有其他人遇到过这个问题吗
为什么我的产品的输出不会像往常一样突然积累在expect的缓冲区中
有没有什么特殊的角色会告诉你,你希望停止这样做
我还有什么地方做错了吗
还有其他解决办法的建议吗
非常感谢您抽出时间。每当我遇到与expect有关的此类问题时,我会首先使用exp_internal命令,该命令会转储大量关于缓冲区状态以及模式匹配方式/是否匹配的非常有用的信息。如果错误可以随意复制,这可能会很有用,但不幸的是,这非常罕见。大部分时间,它所做的只是阻止我的客户监控测试结果。无论出于何种原因,expect开发人员决定使用-f选项复制输出,而不是重定向输出。是否有办法防止此输出显示到脚本中的终端?谢谢你的帮助。如果使用-f选项,则无论指定0还是1作为值,它都会记录信息。在我看来,这似乎有悖常理,但它确实有效。