ct_telnet
Common Test specific layer on top of telnet client ct_telnet_client.erl
Common Test specific layer on top of telnet client ct_telnet_client.erl
Use this module to set up telnet connections, send commands and
perform string matching on the result.
See the unix_telnet
manual page for information about how to use
ct_telnet
, and configure connections, specifically for unix hosts.
The following default values are defined in ct_telnet
:
Connection timeout = 10 sec (time to wait for connection) Command timeout = 10 sec (time to wait for a command to return) Max no of reconnection attempts = 3 Reconnection interval = 5 sek (time to wait in between reconnection attempts) Keep alive = true (will send NOP to the server every 8 sec if connection is idle) Polling limit = 0 (max number of times to poll to get a remaining string terminated) Polling interval = 1 sec (sleep time between polls)
These parameters can be altered by the user with the following configuration term:
{telnet_settings, [{connect_timeout,Millisec}, {command_timeout,Millisec}, {reconnection_attempts,N}, {reconnection_interval,Millisec}, {keep_alive,Bool}, {poll_limit,N}, {poll_interval,Millisec}]}.
Millisec = integer(), N = integer()
Enter the telnet_settings
term in a configuration
file included in the test and ct_telnet will retrieve the information
automatically. Note that keep_alive
may be specified per connection if
required. See unix_telnet
for details.
Logging
The default logging behaviour of ct_telnet
is to print information
to the test case HTML log about performed operations and commands
and their corresponding results. What won't be printed to the HTML log
are text strings sent from the telnet server that are not explicitly
received by means of a ct_telnet
function such as expect/3
.
ct_telnet
may however be configured to use a special purpose event handler,
implemented in ct_conn_log_h
, for logging all telnet traffic.
To use this handler, you need to install a Common Test hook named
cth_conn_log
. Example (using the test suite info function):
suite() -> [{ct_hooks, [{cth_conn_log, [{conn_mod(),hook_options()}]}]}].
conn_mod()
is the name of the common_test module implementing
the connection protocol, i.e. ct_telnet
.
The cth_conn_log
hook performs unformatted logging of telnet data to
a separate text file. All telnet communication is captured and printed,
including arbitrary data sent from the server. The link to this text file
can be found on the top of the test case HTML log.
By default, data for all telnet connections is logged in one common
file (named default
), which might get messy e.g. if multiple telnet
sessions are running in parallel. It is therefore possible to create a
separate log file for each connection. To configure this, use the hook
option hosts
and list the names of the servers/connections that will be
used in the suite. Note that the connections must be named for this to work
(see the open
function below).
The hook option named log_type
may be used to change the cth_conn_log
behaviour. The default value of this option is raw
, which results in the
behaviour described above. If the value is set to html
, all telnet
communication is printed to the test case HTML log instead.
All cth_conn_log
hook options described above can also be specified in
a configuration file with the configuration variable ct_conn_log
. Example:
{ct_conn_log, [{ct_telnet,[{log_type,raw}, {hosts,[key_or_name()]}]}]}
Note that hook options specified in a configuration file will overwrite any hardcoded hook options in the test suite!
Logging example
The following ct_hooks
statement will cause printing of telnet traffic
to separate logs for the connections named server1
and server2
.
Traffic for any other connections will be logged in the default telnet log.
suite() -> [{ct_hooks, [{cth_conn_log, [{ct_telnet,[{hosts,[server1,server2]}]}]}]}].
As previously explained, the above specification could also be provided by means of an entry like this in a configuration file:
{ct_conn_log, [{ct_telnet,[{hosts,[server1,server2]}]}]}.
in which case the ct_hooks
statement in the test suite may simply look
like this:
suite() -> [{ct_hooks, [{cth_conn_log, []}]}].
Functions
close(Connection) -> ok | {error, Reason}
Connection = connection() (see module ct_telnet)
Reason = term()
Close the telnet connection and stop the process managing it.
A connection may be associated with a target name and/or a handle.
If Connection
has no associated target name, it may only
be closed with the handle value (see the open/4
function).
cmd(Connection, Cmd) -> {ok, Data} | {error, Reason}
Equivalent to cmd(Connection, Cmd, []).
cmd(Connection, Cmd, Opts) -> {ok, Data} | {error, Reason}
Connection = connection() (see module ct_telnet)
Cmd = string()
Opts = [Opt]
Opt = {timeout, timeout()} | {newline, boolean()}
Data = [string()]
Reason = term()
Send a command via telnet and wait for prompt.
This function will by default add a newline to the end of the
given command. If this is not desired, the option
{newline,false}
can be used. This is necessary, for example,
when sending telnet command sequences (prefixed with the
Interprete As Command, IAC, character).
The option timeout
specifies how long the client shall wait for
prompt. If the time expires, the function returns
{error,timeout}
. See the module description for information
about the default value for the command timeout.
cmdf(Connection, CmdFormat, Args) -> {ok, Data} | {error, Reason}
Equivalent to cmdf(Connection, CmdFormat, Args, []).
cmdf(Connection, CmdFormat, Args, Opts) -> {ok, Data} | {error, Reason}
Connection = connection() (see module ct_telnet)
CmdFormat = string()
Args = list()
Opts = [Opt]
Opt = {timeout, timeout()} | {newline, boolean()}
Data = [string()]
Reason = term()
Send a telnet command and wait for prompt (uses a format string and list of arguments to build the command).
See cmd/3 further description.
expect(Connection, Patterns) -> term()
Equivalent to expect(Connections, Patterns, []).
expect(Connection, Patterns, Opts) -> {ok, Match} | {ok, MatchList, HaltReason} | {error, Reason}
Connection = connection() (see module ct_telnet)
Patterns = Pattern | [Pattern]
Pattern = string() | {Tag, string()} | prompt | {prompt, Prompt}
Prompt = string()
Tag = term()
Opts = [Opt]
Opt = {idle_timeout, IdleTimeout} | {total_timeout, TotalTimeout} | repeat | {repeat, N} | sequence | {halt, HaltPatterns} | ignore_prompt | no_prompt_check | wait_for_prompt | {wait_for_prompt, Prompt}
IdleTimeout = infinity | integer()
TotalTimeout = infinity | integer()
N = integer()
HaltPatterns = Patterns
MatchList = [Match]
Match = RxMatch | {Tag, RxMatch} | {prompt, Prompt}
RxMatch = [string()]
HaltReason = done | Match
Reason = timeout | {prompt, Prompt}
Get data from telnet and wait for the expected pattern.
Pattern
can be a POSIX regular expression. The function
returns as soon as a pattern has been successfully matched (at least one,
in the case of multiple patterns).
RxMatch
is a list of matched strings. It looks
like this: [FullMatch, SubMatch1, SubMatch2, ...]
where FullMatch
is the string matched by the whole
regular expression and SubMatchN
is the string that
matched subexpression no N
. Subexpressions are
denoted with '(' ')' in the regular expression
If a Tag
is given, the returned Match
will also include the matched Tag
. Else, only
RxMatch
is returned.
The idle_timeout
option indicates that the function
shall return if the telnet client is idle (i.e. if no data is
received) for more than IdleTimeout
milliseconds. Default
timeout is 10 seconds.
The total_timeout
option sets a time limit for
the complete expect operation. After TotalTimeout
milliseconds, {error,timeout}
is returned. The default
value is infinity
(i.e. no time limit).
The function will return when a prompt is received, even if no
pattern has yet been matched. In this event,
{error,{prompt,Prompt}}
is returned.
However, this behaviour may be modified with the
ignore_prompt
or no_prompt_check
option, which
tells expect
to return only when a match is found or after a
timeout.
If the ignore_prompt
option is used,
ct_telnet
will ignore any prompt found. This option
is useful if data sent by the server could include a pattern that
would match the prompt regexp (as returned by
TargedMod:get_prompt_regexp/0
), but which should not
cause the function to return.
If the no_prompt_check
option is used,
ct_telnet
will not search for a prompt at all. This
is useful if, for instance, the Pattern
itself
matches the prompt.
The wait_for_prompt
option forces ct_telnet
to wait until the prompt string has been received before returning
(even if a pattern has already been matched). This is equal to calling:
expect(Conn, Patterns++[{prompt,Prompt}], [sequence|Opts])
.
Note that idle_timeout
and total_timeout
may abort the operation of waiting for prompt.
The repeat
option indicates that the pattern(s)
shall be matched multiple times. If N
is given, the
pattern(s) will be matched N
times, and the function
will return with HaltReason = done
.
The sequence
option indicates that all patterns
shall be matched in a sequence. A match will not be concluded
untill all patterns are matched.
Both repeat
and sequence
can be
interrupted by one or more HaltPatterns
. When
sequence
or repeat
is used, there will
always be a MatchList
returned, i.e. a list of
Match
instead of only one Match
. There
will also be a HaltReason
returned.
Examples:
expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],
[sequence,{halt,[{nnn,"NNN"}]}]).
will try to match
"ABC" first and then "XYZ", but if "NNN" appears the function will
return {error,{nnn,["NNN"]}}
. If both "ABC" and "XYZ"
are matched, the function will return
{ok,[AbcMatch,XyzMatch]}
.
expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],
[{repeat,2},{halt,[{nnn,"NNN"}]}]).
will try to match
"ABC" or "XYZ" twice. If "NNN" appears the function will return
with HaltReason = {nnn,["NNN"]}
.
The repeat
and sequence
options can be
combined in order to match a sequence multiple times.
format_data(How, X2) -> term()
get_data(Connection) -> {ok, Data} | {error, Reason}
Connection = connection() (see module ct_telnet)
Data = [string()]
Reason = term()
Get all data that has been received by the telnet client
since the last command was sent. Note that only newline terminated
strings are returned. If the last string received has not yet
been terminated, the connection may be polled automatically until
the string is complete. The polling feature is controlled
by the poll_limit
and poll_interval
config values and is
by default disabled (meaning the function will immediately
return all complete strings received and save a remaining
non-terminated string for a later get_data
call).
open(Name) -> {ok, Handle} | {error, Reason}
Equivalent to open(Name, telnet).
open(Name, ConnType) -> {ok, Handle} | {error, Reason}
Name = target_name()
ConnType = connection_type() (see module ct_telnet)
Handle = handle() (see module ct_telnet)
Reason = term()
Open a telnet connection to the specified target host.
open(KeyOrName, ConnType, TargetMod) -> {ok, Handle} | {error, Reason}
Equivalent to open(KeyOrName, ConnType, TargetMod, []).
open(KeyOrName, ConnType, TargetMod, Extra) -> {ok, Handle} | {error, Reason}
KeyOrName = Key | Name
Key = atom()
Name = target_name() (see module ct)
ConnType = connection_type()
TargetMod = atom()
Extra = term()
Handle = handle()
Reason = term()
Open a telnet connection to the specified target host.
The target data must exist in a configuration file. The connection
may be associated with either Name
and/or the returned
Handle
. To allocate a name for the target,
use ct:require/2
in a test case, or use a
require
statement in the suite info function
(suite/0
), or in a test case info function.
If you want the connection to be associated with Handle
only
(in case you need to open multiple connections to a host for example),
simply use Key
, the configuration variable name, to
specify the target. Note that a connection that has no associated target
name can only be closed with the handle value.
TargetMod
is a module which exports the functions
connect(Ip,Port,KeepAlive,Extra)
and get_prompt_regexp()
for the given TargetType
(e.g. unix_telnet
).
See also: ct:require/2.
send(Connection, Cmd) -> ok | {error, Reason}
Equivalent to send(Connection, Cmd, []).
send(Connection, Cmd, Opts) -> ok | {error, Reason}
Connection = connection() (see module ct_telnet)
Cmd = string()
Opts = [Opt]
Opt = {newline, boolean()}
Reason = term()
Send a telnet command and return immediately.
This function will by default add a newline to the end of the
given command. If this is not desired, the option
{newline,false}
can be used. This is necessary, for example,
when sending telnet command sequences (prefixed with the
Interprete As Command, IAC, character).
The resulting output from the command can be read with
get_data/1
or expect/2/3
.
sendf(Connection, CmdFormat, Args) -> ok | {error, Reason}
Equivalent to sendf(Connection, CmdFormat, Args, []).
sendf(Connection, CmdFormat, Args, Opts) -> ok | {error, Reason}
Connection = connection() (see module ct_telnet)
CmdFormat = string()
Args = list()
Opts = [Opt]
Opt = {newline, boolean()}
Reason = term()
Send a telnet command and return immediately (uses a format string and a list of arguments to build the command).