This script, written in perl, is supposed to be a small testsuit for any kind of program/device which uses commandline input, such as the Cisco PIX.

The program uses a simple technique which can be compared with a stack. Any test script contains these steps:

  1. connect to some host for the test using e.g. ssh or telnet
  2. wait for some pattern to appear from the foreign host; if the pattern matches, true otherwise false is pushed on the stack.
  3. several such patterns can be defined which push their results on the stack.
  4. to make logical operations one can use the operators and, or and not to modify the results on the stack
  5. based on the top most stack element, the script can display warnings or error messages and cancel its execution.


You can find the tar archive here. A SHA1 fingerprint of this package can be found here. All the files can be viewed here.

Here are some examples and the library.


In case you want to discuss anything regarding this project, you can discuss it here.

Installation requirements

To run the script, the perl module Expect must be installed. On Debian systems, this can be found in the package libexpect-perl.

Commandline syntax

Usage: testify [--debug=LEVEL] [--chdir=DIR] [--define="LABELn=VALUEn"]
               [--libpath="DIR1:DIR2"] FILE [FILE] [FILE]
  --debug     define the debuglevel to use. level 10 shows information about
              the connect processes, 50 about the control structure
              execution and 100 shows the startup process.
              The default is 0.
  --chdir     defines the default start directory where the start script
              should be found. The default is the current directory.
  --define    using this parameter one can define a label as with the
              'define' command. This way the same scripts can be used e.g.
              for various hosts. This option can be repeated several times.
  --libpath   define the paths where the parser looks for library calls; if
              more than one directory is needed, they can be separated by the
              colon character
  FILE        the file to start the execution. If several files are
              specified, they are executed in the given order.

Control structures

The control statements must always be on a single line and not mixed with any commands.


if true
  echo "ok"


if true echo "ok" endif


syntax: if … else … endif

execute the else block if not any of the other if or elseif was executed.


syntax: if … elseif … endif

if the if or elseif block before was not executed, try another condition.


syntax: if … endif

terminate the if block.


syntax: if true … endif, if false … endif, if true … else … endif, if <LABEL> <OP> <VALUE> … endif


if true
  echo "inside the if statement."


if testlabel eq "test"
  echo "test matched."

if the value on the stack is true (or false), the following block gets executed. Otherwise, it is skipped and any following endif or else block gets parsed.

If the 3 argument version is used, <LABEL> is the name of the label (without the surrounding hashes), <OP> is the comparison operator and <VALUE> is the value to compare with.

Possible operators are ==, !=, <, >, , >= for numeric comparison and eq, ne, lt, gt, le and ge for string comparison.

NOTE: If the statement is used in the form 'if true' or 'if false' one item from the stack gets removed right after the execution of the 'if' command!


syntax: return, return true, return false

the return command terminates the current file immediately. If its used with an argument, which must be true or false, this value is left on the stack after the file termination.

Available script commands


syntax: and, and <n>, and all

pop the two last elements off the stack, 'and' the two values and push the result back on the stack. In case <n> or all is specified, this operation is performed n times or for all elements on the stack.


syntax: argument <LABEL>

example: argument HOST

this command can only be used inside a library function. It gets the next argument from the argument stack. This way, the arguments are passed into the library and moved into the label variables.

NOTE: The used labels are always global. So far, no local labels are supported.


syntax: ask <hide|echo> <LABEL> ”<text>”

example: ask hide PASS “password: ”

get interactive user input, e.g. passwords. This is useful if you don't want to store passwords in your scripts, but can be used for any kind of input as well.

The second parameter must be hide or echo. If it is set to 'hide' character echoing to the users tty will be turned off. For this, the unix command stty must be available, otherwise echoing remains enabled. When set to echo the user input will be visible.

The third parameter <LABEL> specifies a label, just like the ones you can define with define. The user input will be stored in the label variable and can be used later in your script, e.g.:

ask hide PASS "password: "
send "#PASS#\n"

The last parameter specifies the text prompt which will be shown to the user.


syntax: call <FUNCTION> <ARG1> <ARG2> <ARGn> …

example: call ping “www.google.de

call a function which can be found in the libary path. The filename must be exactly like the '<FUNCTION>' argument. The suffix .txt is optional. The call command is handled like 'include', but the arguments can be passed more easily.

NOTE: To make the call command simple to understand, please have a look at the provided example of the ping command.


syntax: chdir <PATH>

change the current working directory to <PATH>. If the path is relative, this is relative to the currently used working directory.


syntax: connect ”<CMD>”

example: connect “ssh localhost”

connect to some host using the specified command <CMD>.


syntax: define <LABEL> ”<VALUE>”

example: define HOST “www.harry-b.de

example: echo “host: #HOST#”

define a label which can be used in any kind of command argument. label names must only use letters A-Z, 0-9 and _. Any lowercase letters will silently be converted to uppercase.

To use a label in any commands argument, simply surround it with hashes, e.g. #HOST#.

default labels:

  • #buffer# - the buffer returned by the last receive command
  • #cwd# - the current working directory
  • #libpath# - the current library path
  • #pn# - the nth back reference of the last match where n is [1..9]
  • #sendslow# - the current sendslow value
  • #timeout# - the current timeout value


syntax: disconnect

disconnect from the current connection.


syntax: echo ”<message>”

send <message> to the standard output.


syntax: error ”<message>”

pop the last element off the stack and in case it is false, display the error message and terminate the script.


syntax: foreach <ELEMENTS> do <COMMAND>

example: foreach “e1 e2 e3” do echo \”argument: $i$\”

the foreach command loops through all elements of the string <ELEMENTS>.

The delimiter of the elements is space.

For each element, the command <COMMAND> is executed.

NOTE: The quotation marks for the <COMMAND> part must be escaped to make it to the final command execution.


syntax: include <FILENAME>

includes the file <FILENAME> recursively. The file will be executed at the current position.

NOTE: At the end of each included file, the stack must be at the same position as it was at its beginning. Otherwise, an error terminates the script execution.


syntax: match <TYPE> <PATTERN>

search for <PATTERN> in the last received output. if the pattern matches, true is pushed on the stack, otherwise false. This command can only be executed if there is an active connection and after at least one receive command has been executed.

<TYPE> is the pattern matching type. regex matches for a regular expression, iregex uses an insensitive regular expression.

Labels are set accordingly, as described at the define command.


syntax: not, not <n>, not all

pop the last element off the stack, reverse its value and push the result back on the stack. In case <n> or all is specified, this operation is performed n times or for all elements on the stack.


syntax: or, or <n>, or all

pop the two last elements off the stack, or the two values and push the result back on the stack.

In case <n> or all is specified, this operation is performed n times or for all elements on the stack.


syntax: pop, pop <n>, pop all

pop the last, n or all elements off the stack. The results are just dumped.


syntax: push, push true, push false

push the value true or false on the stack. In case it is used without argument, the last element on the stack is duplicated.


syntax: receive <TYPE> ”<PATTERN>”

wait for the specified pattern <PATTERN> to appear from the remote application. Usually this is the prompt of the remote system. If the pattern was found, true is pushed on the stack, otherwise false.

<TYPE> is the pattern matching type. Right now, only regex is supported.


syntax: send ”<MESSAGE>”

send the specified message <MESSAGE> to the connection.

NOTE: In case you send a command to a remote machine, make sure to send the \n for <CR> at the end of the line!


syntax: set <VARIABLE> ”<VALUE>”

example: set timeout “3”

set the specified variable <VARIABLE> to the value of <VALUE>.

possible variables are:

  • libpath - modify the current library path. The new value replaces the currently used setting.
  • sendslow - this variable is used as delay timer (in seconds) for all commands sent to the remote application. For slow modem connections it might be necessary to use some other value than 0.
  • timeout - this variable specifies the timeout (in seconds) the receive command waits for results.


syntax: show, show <n>, show all

print the last, n or all elements on the stack to standard output.

Note: this function does not modify any data on the stack. Its just there for debugging.


syntax: subst <LABEL> <PATTERN> <REPLACE>

example: subst HOSTNAME “\.harry-b\.de” ””

substitute the regular expression <PATTERN> with <REPLACE> in label <LABEL>.


syntax: wait <SECONDS>

wait some seconds before executing the next command.


syntax: warning ”<message>”

pop the last element off the stack and in case it is false, display the warning message. The script is not terminated.

harry/testify.txt · Last modified: 2006/03/26 14:47 (external edit)
Locations of visitors to this page

Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki