查看源码 ct_telnet (common_test v1.27.5)
Common Test
特定层,位于 Telnet 客户端 ct_telnet_client.erl
之上。
使用此模块来设置 Telnet 连接、发送命令并对结果执行字符串匹配。有关如何使用 ct_telnet
和配置连接的信息,特别是对于 UNIX 主机,请参阅 unix_telnet
手册页。
ct_telnet
中定义的默认值
- 连接超时(等待连接的时间)= 10 秒
- 命令超时(等待命令返回的时间)= 10 秒
- 最大重连尝试次数 = 3
- 重连间隔(重连尝试之间等待的时间)= 5 秒
- 保持活动(如果连接空闲,每 8 秒向服务器发送 NOP)=
true
- 轮询限制(为获取剩余的终止字符串而轮询的最大次数)= 0
- 轮询间隔(轮询之间的睡眠时间)= 1 秒
- 默认情况下,禁用 telnet 套接字的 TCP_NODELAY 选项(设置为
false
)
用户可以使用以下配置项修改这些参数
{telnet_settings, [{connect_timeout,Millisec},
{command_timeout,Millisec},
{reconnection_attempts,N},
{reconnection_interval,Millisec},
{keep_alive,Bool},
{poll_limit,N},
{poll_interval,Millisec},
{tcp_nodelay,Bool}]}.
Millisec = integer(), N = integer()
在测试中包含的配置文件中输入 telnet_settings
项,ct_telnet
会自动检索信息。
如有必要,可以为每个连接指定 keep_alive
。有关详细信息,请参阅 unix_telnet
。
日志记录
ct_telnet
的默认日志记录行为是将有关执行的操作、命令及其相应结果的信息打印到测试用例 HTML 日志。以下内容不会打印到 HTML 日志:从 Telnet 服务器发送的文本字符串,这些字符串不是由 ct_telnet
函数显式接收的,例如 expect/3
。但是,可以配置 ct_telnet
使用在 ct_conn_log_h
中实现的特殊用途的事件处理程序来记录所有 Telnet 流量。要使用此处理程序,请安装名为 cth_conn_log
的 Common Test
钩子。示例(使用测试套件信息函数)
suite() ->
[{ct_hooks, [{cth_conn_log, [{conn_mod(),hook_options()}]}]}].
conn_mod()
是实现连接协议的 Common Test
模块的名称,即 ct_telnet
。
cth_conn_log
钩子将 Telnet 数据以未格式化的形式记录到单独的文本文件中。捕获并打印所有 Telnet 通信,包括从服务器发送的任何数据。此文本文件的链接位于测试用例 HTML 日志的顶部。
默认情况下,所有 Telnet 连接的数据都记录在一个公共文件(名为 default
)中,这可能会很混乱,例如,如果多个 Telnet 会话并行运行。因此,可以为每个连接创建一个单独的日志文件。要配置此项,请使用钩子选项 hosts
并列出要在套件中使用的服务器/连接的名称。连接必须命名才能正常工作(请参阅 ct_telnet:open/1,2,3,4
)。
钩子选项 log_type
可用于更改 cth_conn_log
的行为。此选项的默认值为 raw
,这将导致上述行为。如果该值设置为 html
,则所有 Telnet 通信都将打印到测试用例 HTML 日志中。
对于原始日志,prefix
选项可用于调整添加到连接日志的前缀数据。此选项的默认值为 disabled
,这将导致不使用前缀数据。如果该值设置为 full
,则前缀包含时间戳和其他信息。如果该值设置为 short
,则前缀仅包含人类可读的时间戳。
上述所有 cth_conn_log
钩子选项也可以在配置文件中使用配置变量 ct_conn_log
指定。
示例
{ct_conn_log, [{ct_telnet,[{log_type,raw},
{hosts,[key_or_name()]}]}]}
注意
配置文件中指定的钩子选项会覆盖测试套件中的任何硬编码钩子选项。
日志记录示例
以下 ct_hooks
语句会导致将 Telnet 流量打印到 server1
和 server2
连接的单独日志中。任何其他连接的流量都记录在默认 Telnet 日志中。
suite() ->
[{ct_hooks,
[{cth_conn_log, [{ct_telnet,[{hosts,[server1,server2]}]}]}]}].
如前所述,此规范也可以通过配置文件中如下所示的条目提供
{ct_conn_log, [{ct_telnet,[{hosts,[server1,server2]}]}]}.
在这种情况下,测试套件中的 ct_hooks
语句可以如下所示
suite() ->
[{ct_hooks, [{cth_conn_log, []}]}].
另请参阅
摘要
类型
对与 handle
或 target_name
关联的已打开的 Telnet 连接的引用。
Telnet 连接类型,有效值:“telnet”| “ts1”| “ts2”。
请参阅 cmd/3
获取说明。
与特定目标类型的所有可能提示匹配的正则表达式。regexp
不得有任何组,也就是说,在匹配时,re:run/3
(在 STDLIB 中)必须返回一个包含单个元素的列表。
函数
关闭 Telnet 连接并停止管理它的进程。
通过 Telnet 发送命令并等待提示。
发送 Telnet 命令并等待提示(使用格式字符串和参数列表来构建命令)。
从 Telnet 获取数据并等待预期的模式。
获取自上次发送命令以来 Telnet 客户端收到的所有数据。仅返回以换行符结尾的字符串。如果最后接收到的字符串尚未终止,则可以自动轮询连接,直到字符串完成。
打开到指定目标主机的 Telnet 连接。
打开到指定目标主机的 Telnet 连接。
发送 Telnet 命令并立即返回。
发送 Telnet 命令并立即返回(使用格式字符串和参数列表来构建命令)。
类型
-type connection() :: handle() | {ct:target_name(), connection_type()} | ct:target_name().
对与 handle
或 target_name
关联的已打开的 Telnet 连接的引用。
-type connection_type() :: telnet | ts1 | ts2.
Telnet 连接类型,有效值:“telnet”| “ts1”| “ts2”。
-type handle() :: ct:handle().
特定 Telnet 连接的句柄,请参阅模块 ct
。
请参阅 cmd/3
获取说明。
-type prompt_regexp() :: string().
与特定目标类型的所有可能提示匹配的正则表达式。regexp
不得有任何组,也就是说,在匹配时,re:run/3
(在 STDLIB 中)必须返回一个包含单个元素的列表。
函数
-spec close(Connection) -> ok | {error, Reason} when Connection :: connection(), Reason :: already_closed | term().
关闭 Telnet 连接并停止管理它的进程。
连接可以与目标名称和/或句柄关联。如果 Connection
没有关联的目标名称,则只能使用句柄值关闭(请参阅 ct_telnet:open/4
)。
-spec cmd(Connection, Cmd) -> {ok, Data} | {error, Reason} when Connection :: connection(), Cmd :: iodata(), Data :: string(), Reason :: term().
-spec cmd(Connection, Cmd, Opts) -> {ok, Data} | {error, Reason} when Connection :: connection(), Cmd :: iodata(), Opts :: [{timeout, Timeout} | newline_option()] | Timeout, Timeout :: integer(), Data :: string(), Reason :: term().
通过 Telnet 发送命令并等待提示。
默认情况下,此函数将“\n”添加到指定命令的末尾。如果不需要此操作,请使用选项 {newline,false}
。例如,当发送带有字符解释为命令 (IAC) 前缀的 Telnet 命令序列时,这是必要的。如果需要不同于 “\n” 的行尾,也可以使用选项 {newline,string()}
,例如 {newline,"\r\n"}
,以添加回车符和换行符。
选项 timeout
指定客户端必须等待提示的时间长度。如果时间到期,该函数将返回 {error,timeout}
。有关命令超时的默认值的信息,请参阅本模块开头的默认值列表。
-spec cmdf(Connection, CmdFormat, Args) -> {ok, Data} | {error, Reason} when Connection :: connection(), CmdFormat :: io:format(), Args :: [term()], Data :: string(), Reason :: term().
-spec cmdf(Connection, CmdFormat, Args, Opts) -> {ok, Data} | {error, Reason} when Connection :: connection(), CmdFormat :: io:format(), Args :: [term()], Opts :: [{timeout, Timeout} | newline_option()] | Timeout, Timeout :: integer(), Data :: string(), Reason :: term().
发送 Telnet 命令并等待提示(使用格式字符串和参数列表来构建命令)。
有关详细信息,请参阅 ct_telnet:cmd/3
。
-spec expect(Connection, Patterns) -> {ok, Match} | {ok, Match, HaltReason} | {error, Reason} | no_return() when Connection :: connection(), Patterns :: Pattern | [Pattern], Pattern :: PatternString | {Tag, PatternString}, Tag :: term(), PatternString :: unicode:charlist(), Match :: MatchResult | [MatchResult], MatchResult :: [CaptureData | {Tag, CaptureData}] | [[CaptureData | {Tag, CaptureData}]], CaptureData :: string() | {error, string(), binary()} | {incomplete, string(), binary()}, HaltReason :: MatchResult, Reason :: term().
-spec expect(Connection, Patterns, Opts) -> {ok, Match} | {ok, Match, HaltReason} | {error, Reason} | no_return() when Connection :: connection(), Patterns :: Pattern | [Pattern], Pattern :: PatternString | {Tag, PatternString}, Tag :: term(), PatternString :: unicode:charlist(), Opts :: [Option], Option :: {idle_timeout, non_neg_integer()} | {total_timeout, non_neg_integer()} | ignore_prompt | no_prompt_check | wait_for_prompt | repeat | {repeat, non_neg_integer()} | sequence | {halt, Patterns}, Match :: MatchResult | [MatchResult], MatchResult :: [CaptureData | {Tag, CaptureData}] | [[CaptureData | {Tag, CaptureData}]], CaptureData :: string() | {error, string(), binary()} | {incomplete, string(), binary()}, HaltReason :: MatchResult, Reason :: term().
从 Telnet 获取数据并等待预期的模式。
Pattern
可以是 POSIX 正则表达式。当模式成功匹配时(在多个模式的情况下,至少匹配一个),该函数返回。
RxMatch
是匹配的字符串列表。它的形式如下 [FullMatch, SubMatch1, SubMatch2, ...]
,其中 FullMatch
是整个正则表达式匹配的字符串,SubMatchN
是与子表达式编号 N
匹配的字符串。子表达式在正则表达式中使用 '(' ')'
表示。
如果指定了 Tag
,则返回的 Match
还包括匹配的 Tag
。否则,仅返回 RxMatch
。
选项
idle_timeout
- 指示如果 Telnet 客户端空闲(即,如果未收到任何数据)超过IdleTimeout
毫秒,则该函数必须返回。默认超时为 10 秒。total_timeout
- 为完整的expect
操作设置时间限制。在TotalTimeout
毫秒后,将返回{error,timeout}
。默认值为infinity
(即,没有时间限制)。ignore_prompt | no_prompt_check
- >当收到提示时,即使尚未匹配任何模式,该函数也会返回,并且返回{error,{prompt,Prompt}}
。但是,可以使用选项ignore_prompt
或选项no_prompt_check
修改此行为,这些选项指示expect
仅在找到匹配项或超时后返回。ignore_prompt
-ct_telnet
会忽略任何找到的提示符。如果服务器发送的数据可能包含与提示符regexp
(由TargedMod:get_prompt_regexp/0
返回)匹配的模式,但又不想因此导致函数返回,则此选项非常有用。no_prompt_check
-ct_telnet
完全不搜索提示符。例如,如果Pattern
本身匹配提示符,则此选项非常有用。wait_for_prompt
- 强制ct_telnet
等待直到收到提示符字符串才返回(即使已经匹配到模式)。这等同于调用expect(Conn, Patterns++[{prompt,Prompt}], [sequence|Opts])
。注意,选项idle_timeout
和total_timeout
可以中止等待提示符的操作。repeat | repeat, N
- 模式必须匹配多次。如果指定了N
,则模式匹配N
次,并且函数返回HaltReason = done
。此选项可以被一个或多个HaltPatterns
中断。MatchList
总是被返回,也就是说,返回一个Match
列表,而不是仅返回一个Match
。并且还会返回HaltReason
。sequence
- 所有模式必须按顺序匹配。在所有模式都匹配之前,匹配不会结束。此选项可以被一个或多个HaltPatterns
中断。MatchList
总是被返回,也就是说,返回一个Match
列表,而不是仅返回一个Match
。并且还会返回HaltReason
。
示例 1
expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],[sequence,{halt,[{nnn,"NNN"}]}])
首先尝试匹配 "ABC"
,然后匹配 "XYZ"
,但如果出现 "NNN"
,则函数返回 {error,{nnn,["NNN"]}}
。如果 "ABC"
和 "XYZ"
都匹配,则函数返回 {ok,[AbcMatch,XyzMatch]}
。
示例 2
expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],[{repeat,2},{halt,[{nnn,"NNN"}]}])
尝试匹配 "ABC"
或 "XYZ"
两次。如果出现 "NNN"
,则函数返回 HaltReason = {nnn,["NNN"]}
。
可以组合选项 repeat
和 sequence
来多次匹配序列。
-spec get_data(Connection) -> {ok, Data} | {error, Reason} when Connection :: connection(), Data :: string(), Reason :: term().
获取自上次发送命令以来 Telnet 客户端收到的所有数据。仅返回以换行符结尾的字符串。如果最后接收到的字符串尚未终止,则可以自动轮询连接,直到字符串完成。
轮询功能由配置值 poll_limit
和 poll_interval
控制,默认情况下禁用。这意味着函数会立即返回所有已接收的完整字符串,并保存剩余的未终止字符串,以便在稍后的 get_data
调用中使用。
-spec open(Name) -> {ok, Handle} | {error, Reason} when Name :: atom(), Handle :: handle(), Reason :: term().
等效于 open(Name, telnet)
。
-spec open(Name, ConnType) -> {ok, Handle} | {error, Reason} when Name :: atom(), ConnType :: connection_type(), Handle :: handle(), Reason :: term().
打开到指定目标主机的 Telnet 连接。
-spec open(KeyOrName, ConnType, TargetMod) -> {ok, Handle} | {error, Reason} when KeyOrName :: ct:key_or_name(), ConnType :: connection_type(), TargetMod :: module(), Handle :: handle(), Reason :: term().
-spec open(KeyOrName, ConnType, TargetMod, Extra) -> {ok, Handle} | {error, Reason} when KeyOrName :: ct:key_or_name(), ConnType :: connection_type(), TargetMod :: module(), Extra :: term(), Handle :: handle(), Reason :: term().
打开到指定目标主机的 Telnet 连接。
目标数据必须存在于配置文件中。连接可以与 Name
和/或返回的 Handle
关联。要为目标分配名称,请使用以下替代方案之一:
- 在测试用例中使用
ct:require/2
- 在套件信息函数 (
suite/0
) 中使用require
语句 - 在测试用例信息函数中使用
require
语句
如果希望连接仅与 Handle
关联(例如,如果需要打开到主机的多个连接),请使用 Key
(配置变量名称)来指定目标。请注意,没有关联目标名称的连接只能使用 Handle
值关闭。
TargetMod
是一个模块,它为指定的 TargetType
(例如,unix_telnet
)导出函数 connect(Ip, Port, KeepAlive, Extra)
和 get_prompt_regexp()
。
另请参阅 ct:require/2
。
-spec send(Connection, Cmd) -> ok | {error, Reason} when Connection :: connection(), Cmd :: iodata(), Reason :: term().
-spec send(Connection, Cmd, Opts) -> ok | {error, Reason} when Connection :: connection(), Cmd :: iodata(), Opts :: [newline_option()], Reason :: term().
发送 Telnet 命令并立即返回。
默认情况下,此函数会在指定命令的末尾添加 "\n"。如果不需要这样做,可以使用选项 {newline,false}
。例如,在发送以字符 Interpret As Command (IAC) 开头的 Telnet 命令序列时,这是必要的。如果需要使用除 "\n" 之外的其他行尾符,也可以使用选项 {newline,string()}
,例如 {newline,"\r\n"}
,以添加回车符和换行符。
可以使用 ct_telnet:get_data/2
或 ct_telnet:expect/2,3
读取命令的输出结果。
-spec sendf(Connection, CmdFormat, Args) -> ok | {error, Reason} when Connection :: connection(), CmdFormat :: io:format(), Args :: [term()], Reason :: term().
-spec sendf(Connection, CmdFormat, Args, Opts) -> ok | {error, Reason} when Connection :: connection(), CmdFormat :: io:format(), Args :: [term()], Opts :: [newline_option()], Reason :: term().
发送 Telnet 命令并立即返回(使用格式字符串和参数列表来构建命令)。
有关详细信息,请参阅 ct_telnet:send/3
。