Expect-Lite

Making Expect scripting Simple



Introduction

What is expect-lite? expect-lite is a wrapper for expect, created to make expect programming even easier. The wrapper permits the creation of expect script command files by using a special character(s) at the beginning of each line to indicate the expect-lite action.

Basic expect-lite scripts can be created by simply cutting and pasting text from a terminal window into a script, and adding '>' '<' characters.

Expect-lite is targeted at the verification testing environment, and will produce a Pass/Fail result at the end of the script. However, its use is not limited to this environment.

Features

Expect-lite has many features which make expect-style script writing easy. Such as:

BSD-Style License

Copyright (C) Freescale Semiconductor, Inc. 2005-2007

See the  COPYING for information on usage and redistribution
of this file, and for a DISCLAIMER OF ALL WARRANTIES.

Download

Expect-lite downloads can be found on the Expect-lite Project Page: http://sourceforge.net/projects/expect-lite
The package includes expect-lite, as well as several examples.

Installation

Place expect-lite in your path. Test by typing at the prompt:
expect-lite
If you see the help, then it is ready to go, installation is complete!

See the Installation & Quick Start Guide for more help with tuning expect-lite to your environment.

Automatic Login

Based on the command line arguments passed, expect-lite will do the following:

In the following example of expect-lite:
./expect-lite remote_host=remote-host-018 cmd_file=basic_ping_test.elt user_dir=/etc

expect-lite will log into remote-host-018, change directory to /etc/ and begin to send commands from basic_ping_test.elt to the remote-host. The parameters of remote_host and cmd_file are required, as expect-lite must know what host to log into, and what script (aka command file) to run.

Special Characters

Expect-lite interprets the following special characters at the beginning of each line in the script as:
Char
Action
>
send string to the remote host
>>
send string to remote host, without waiting for prompt (see implementation details)
<
string/regex MUST be received from the remote host in the alloted timeout or the script will FAIL!
-<
if string/regex IS received from the remote host the script will FAIL! (see Not Expect)
#
used to indicate comment lines, and have no effect
;
are also used to indicate comment lines, but are printed to stdout (for logging)
;;
similar to above, but no extra newlines are printed (useful for printing script help)
@
changes the expect timeout value in seconds
$
indicates a static variable which is defined at script invocation (see variables for details)
+
used to add a variable dynamically  (see variables)
+$var increment value of $var by 1 decimal (see repeat loop)
-$var decrement value of $var by 1 decimal
=$var
math functions, perform bitwise and arithmetic operations:  << >> & | ^ * / % + - (see math functions)
~filename
includes a expect-lite automation file, useful for creation of common var files, or 'subprograms/subroutines'
*~filename includes a fail script, which is run if the main script fails (see fail script)
!
indicates an embedded expect line (see embedded expect)
?
c-style if/then/else in the format ?cond?action::else_action (see conditionals)
%
label - used for jumping to labels (see conditionals)

In addition to the above ten special characters, blank lines or lines starting with any non-special character are allowed to make the script file more readable.

Sometimes control characters must be sent to the host. Currently all control characters are supported (from ^@ to ^\):
Control characters must be the first two characters on the line (e.g.[^][A-Z]). The sequence of ^C anywhere else in the line will not be interpreted as a control-C, but rather the two characters '^' 'C'.

Use of Regex in expect-lite

Support of regular expressions in expect-lite are limited by:
  1. Support of regex in standard expect (e.g. including anchors, char-classes and repeats)
  2. Support of regex meta characters (e.g. \t \n are supported, \d is not)
  3. Expect-lite only evaluates lines using regex which begin with '<'  '-<' and '+'
As an example, a range of numbers is valid for an IP address. The following would permit the last octet of the IP address to be 2 digits, but not 3.
> /sbin/ifconfig eth0
<inet addr:10\.29\.200\.[0-9][0-9][ ]
The periods are preceded by a backslash to indicate to regex that a period must be returned rather than the regex dot '.' which indicates any character.

Because regex is always enabled for expected results, some 'escaping' of characters must be done when using '<'. The following characters must be escaped with a backslash to convey their literal meaning:

Example
Escaped
Character
(abc) \(abc\) parenthesis
[abc]
\[abc\] 
square brackets
\
\\
backslash
. \.
period
$ \$
dollar sign

Using Variables

Expect-lite supports two types of variables:
Lines starting with a '$' indicate variables which are assigned and set at script invocation, and therefore are static. In expect-lite variable names will always be preceded with a '$'.

Sometimes it is desirable to bind a variable during the execution of the script. Dynamic variables fill this need by utilizing Expect's built-in regex capture mechanism. Only the portion of the match inside the parenthesis will be bound to the variable. The format of the line is as follows:
+$somevar=text that is not put into the var (text which is put into the var)

Dynamic Variables are always bound to Expect output, meaning text which is returned from the remote host. Therefore something must be sent to the remote host, before text can be returned. A typical usage would be:
> command
+$myvar=command output (capture value) more command output

If the value of the var is successfully captured then expect-lite will print:
Assigned Var:somevar=sometext which is put into the var

If, however the dynamic var is not successfully captured, expect-lite will print:
Assigned Var:somevar=__NO_STRING_CAPTURED__
Avoid using an overly general capture as it will tend to capture too much, or the wrong info. e.g:
> command
+$myvar=\n(.*)
Instead use a specific capture when possible. When capturing the current directory, the current directory will always start with '/', and the path will be made up of a known character set:
> echo $PWD
+$mypwd=\n(/[a-zA-Z0-9/\-_]+)

Expect-lite will print to stdout the value of the assigned variable, assisting the script writer in understanding the value that is bound to the variable during runtime. The value of "__NO_STRING_CAPTURED__" indicates that the regex pattern used did not match the return data. It is best to start using this feature with short scripts targeted at capturing the desired information. Examples can be found in the example section of this readme.

Math Functions with Variables

There are times when writing a script it may be necessary to perform arithmetic or bitwise operations, also known as math functions. Expect-lite inherits expect/tcl math functions and natively supports math/bitwise operations on a variable, using the following slightly odd notation:
$myvar=1
=$myvar + 2 * 10
In the above example, 2 will be multiplied by 10 and added to value of $myvar (1). The result of 21 will be placed in $myvar, overwriting the previous value. Since multiplication has a higher precedence than addition, (2 * 10) will be performed before the addition to $myvar.

Parenthesis may be used to enforce user defined precedence. In the following example, the result will be 23:
$myvar=1
=$myvar + 2 * (10 + 1)

Both bitwise and arithmetic operators are supported with the following precedence (left to right):
bitwise
<< >> & ^ | shift left, shift right, bit and, bit exclusive or, or
arithmetic  * / % + -
multiply, divide, modulo, add, subtract


If $myvar does not exist before the math function, it will be initialized to blank and then math functions will be performed. In the following example the result, $myvar, will be 20:
=$myvar + 2 * 10
However, realistically, only the '+' operator works as expected in the above example. Using other operators will more than likely yield a syntax error:
Warning: Expect-lite: Unable to interpret =$answer1   / 2 * (10 + 1) 
syntax error in expression " / 2 * (10 + 1)": unexpected operator /

Because of the expect/tcl inheritance of math functions, all operations will be performed as integers (or whole numbers) unless a decimal (or real) number is used explicitly. In the following example the result is 2.5:
$five=5
=$myvar + $five / 2.0
However, the following (because of the use of integers) example will have the result of 3:
$five=5
=$myvar + $five / 2

Math functions can be used with static and dynamic variables.

Pseudo Arrays

Expect-lite supports pseudo arrays, which are different from a real array (e.g. item[1], item[2],...). Pseudo arrays are made possible by the fact that variables on the left side of the equals can be dereferenced at assignment time. For example, below, the variable $count will be dereferenced (or resolved) prior to assignment:
$myarray$count=some $value
When placed in a loop with a looping variable of $count, a pseudo array of $myarray1, $myarray2, $myarray3,... will be created. Individual values can be retrieved from the array by using the index (or $count) such as $myarray23.

The pseudo array name (variable + index) must be a valid variable name, in the set of characters (A to Z, a to z, 0 to 9, and underscore) and no spaces.

Constants

Expect-lite Constants are represented as variables which are passed into expect-lite at runtime. Constants will override any script variable already defined inside the script, are immutable, and cannot be changed. Constants can be used to change the behaviour of the script.

For example, one might invoke the following test as:
./expect-lite remote_host=remote-host-018 cmd_file=basic_ping_test.elt user_dir=/etc local_eth=eth2

Inside the script basic_ping_test.txt any reference to $local_eth would be set to eth2, thus allowing the script actions to be changed based on the constant passed at invocation. Constants will override any script variable already defined inside the script.

Shell Variables

Expect-lite allows the use of shell variables, which can be more powerful than the built-in variable mechanism. However shell variables will only be resolved by the shell. For example, assigning current working directory to a shell var:
> PWD=`pwd`
> echo $PWD
However, the following test would fail, since $PWD is a shell variable, not an expect-lite variable:
> PWD=`pwd`
>pwd
< $PWD
Shell variables (or environment variables) must be dereferenced by the shell. Similarly, expect-lite variables must be dereferenced by expect-lite.

It is possible to read a shell variable into an expect-lite variable by using the dynamic variable method:
> echo $PWD
+$mypwd=\n(/[a-zA-Z0-9/\-_]+)

Using Conditionals & Labels

Conditional (if/then/else) statements are natively supported in expect-lite. The conditional uses a c-style syntax with a question mark (?) at the beginning of the line, and double colon to indicate the else statement, using the format ?cond?action::else_action

Although spaces are not required around the conditional characters (? and ::), it is recommended for ease of reading. The comparison operators are: '==',  '!=' ,'>=',  '<=',  '>' and '<'. If the compared values can be evaluated as a numbers, then larger and less than will yield expected results. A simple conditional example:
$age=56
? $age >= 55 ? >echo "freedom at 55!" :: > echo "keep working!"
In the above example if $age is larger than or equal to 55 then the action 'echo "freedom at 55!". If $age is less than 55 then the action 'echo "keep working!"' will be sent.

Each action or else_action is as if it began on a separate line. Since in the above example '>' is used (e.g. >echo) the echo line will be sent to the remote host. Any expect-lite action (see Special Characters) can be placed after the second question mark. For example, an include file may be executed based on a conditional:
$platform=ppc
? $platform == i386 ? ~connect_i386.inc :: ~connect_ppc.inc
In order to make log files more understandable, a message will be printed when a conditional is evaluated, such as:
If: expr { "ppc" == "i386" } |then ~connect_i386.inc|else  ~connect_ppc.inc|result0
The message prints: what was evaluated (expr { "ppc" == "i386" }),  'then', and 'else' actions, as well as a result (0=false)

Labels

Conditionals are limited to a single line. Sometimes this is too limiting, as it would be nice to have several commands be executed based on the success of a conditional. To support this, the concept of labels has been introduced. A label is defined as having the first character a '%'. Although the label line itself does nothing, it provides a location to the conditional to Jump To Label. The following is a simple example of using a conditional in conjunction with a label:
$kmodules_inserted=true
? $kmodules_inserted == false ? %SKIP_CHECK_KMODS
>lsmod | grep nfs
<nfsd
<exportfs
<sunrpc
%SKIP_CHECK_KMODS
When a label is the action of a conditional, there is an implied Jump to Label. Lines between the conditional and the label will be skipped. The Jump to Label action is no longer limited to only jumping forward. (see Looping with Conditionals)

Multiple labels with the same name are permitted. For example, a conditional action may be Jump to Label %SKIP. Although multiple labels of %SKIP may occur in the script, in this example, expect-lite will jump to the next line containing %SKIP. Of course it is easier for the script reader if clearer label names are used. Labels may contain spaces, as in this example:
; === Test conditional jump to label
? $jump == true ?%move along, nothing to see
>echo "1"
>echo "2"
>echo "3"
%move along, nothing to see
To assist reading the logs, the action Jump to Label will generate a message to standard out (captured in the log). From the above example, the following would be printed:
Jumping to label:%move along, nothing to see

Looping with Conditionals & Labels

Simple looping is now supported by allowing jump to label backwards. The Repeat Loop is the easist loop to implement:
; ======== Incrementing Loop ========
$max=5
$count=3
%REPEAT_INC_LOOP
>echo $count
# increment variable
+$count
?if $count <= $max ?%REPEAT_INC_LOOP
Because of jump to label can jump backwards, it is important to assign unique looping labels, such as %REPEAT_INC_LOOP. Unexpected results will occur if non-unique loop label names are used. Non-looping labels, as illustrated in the previous section, are not required to be unique.

Also included in the above example is incrementing an expect-lite variable: +$count
This will add 1 to the value of $count. If $count is not an integer, the value of $count will remain unchanged (can't add 1 to a string).

As part of the looping enhancement, there is infinite loop protection. The maximum amount of looping is defined in expect-lite itself with the variable _el_infinite_loop. This value is decremented with each iteration of all loops for the entire script. Typically this would be in the range of 100 to 1000 to be safe. For example, if a complex expect-lite script had 4 loops each with 100 iterations, the _el_infinite_loop should be set larger than 400.

Expect-lite & Bash

Although not limited to working with bash, bash is invoked upon logging into the remote host, and therefore will be discussed more here.

Since the bash shell is well documented, and supported, and therefore can be leveraged to assist in expect-lite's limitations such as looping and branching (see limitations below). A simple bash loop inside expect-lite can be created for example:
$set=1 2 3 4 5
>for i in $set #expanded by expect-lite
>{
>echo $i #expanded by bash
>}
In the above example, $set is an expect-lite variable, not a bash variable. An expect-lite variable is always declared before its use (e.g. $set= 1 2 3 4 5). If a variable cannot be dereference by expect-lite it is passed to the shell. The loop will execute after the final "}" line is sent to the remote-host. Because of this "execute after" effect, an expect-lite '<' line can not be used within the bash loop.

Another example is the while loop:
$max=5
>i=0
>while [ $i -lt $max ]
>do
>echo $i
>let i+=1
>done
Conditionals via bash are also supported, as in this example:
$max=4
>if [ $max -ne 5 ]; then
>echo "max is not equal to 5"
>else
>echo "we have a winner"
>fi
More complex bash assists can be constructed. For example, one may want to set a looping variable based on the processor type of machine at the time (some hosts may be faster than others). The answer is echo'ed, and then captured using a dynamic variable. Note that that 'proc' is prepended to the answer, as it enables the capture to be much more specific.
>PROC=`uname -i`
>if [ "$PROC" == "i386" ]; then
>echo proc20
>else
>echo proc100
>fi
+loop_counter=\nproc([0-9]+)
Note that 'proc' is outside the parenthesis, and therefore will not be captured into the expect-lite dynamic variable $loop_counter.

Include Files

Include files are a quick way to develop script snippets which can be included into larger scripts or to include a common variable file. When an include file is executed, it is as if the file were just pasted into the script file, and therefore has access to the variable space of the main script, and can modify that variable space as well. In this example, a common variable file is "sourced":
# Source common variable file
~asic_vars.inc

Common functions, such as telnet'ing to the DUT, are a good use of include files:
; === Connect to DUT 
~dut_connect.inc
Include filenames can also be assigned in a variable, such that the files can be declared at the top of the script but used later within the script. For example:
# Source Var file to be used
$asic_include=asic_vars.inc
...
~$asic_include
Fail Script

The purpose of the fail script is to clean up after the failed script, reseting times, deleting temporary files and such. It is a special include script which is declared near the top of the script:
*~clean_up.inc
Should the script fail, the fail script will be "sourced". 

The scope of the fail script is always local to the running script. This allows normal include scripts to declare a separate fail script from the main script. Thus enabling a different clean up mechanism for the include script.

The fail script mechanism can also be used for script development. One the script fails, it is possible to drop expect-lite into interactive mode allowing the script developer to interact the DUT interactively. debug.inc in the following example:
; Press '+++' to end interactive session
>
!interact +++ return
>
# allow script to continue
!set _el(continue) 1
>
; === Continuing Script
>
The above debug fail script places the developer into interactive mode. Once the developer has completed with interactive mode, '+++' is typed and the script continues. In this particular example, a flag is set _el(continue), which allows the main script to continue as if there were no failure.

Embedded Expect

There are situations when expect-lite cannot provide a solution. Rather than force the user to abandon the simplicity of expect-lite, an embedded expect is supported. This functionality is provided to assist expect-lite rather than replace it. Lines beginning with '!' will be interpreted as native expect (see limitations below).

Embedded Expect requires the script writer to know  native expect. It runs with some variable protection, and provides access to expect-lite variables and constants, as well as the expect variable timeout. This permits the script writer to query the timeout, store it away, and then reset the timeout later.
# Preserve old timeout using embedded expect
!set user_namespace(TIMEOUT) $timeout
# set timeout to 15 seconds - max time to wait for login prompts
@15
>telnet $dut_ip
<login
>>root
<assword
>>my_secret
>
# Set the timeout back to old timeout
@$TIMEOUT
Expect-lite variable/values are stored in the tcl array user_namespace() with the variable name as the index name. Constants are stored similarly in the tcl array cli_namespace().

Expect code is collected in islands and executed after an island shore is reached. The island shore is represented by lines that start with any special character, except '#' and blank lines. However, it is recommended that the '>' be used, as this implies a "wait for prompt."

Branching and looping are supported in embedded expect e.g.:
!if { $arch == "ppc" } { 
! puts "\narch is $arch\n"
!}
>
And looping:
!for {set j 1} {$j<6} {incr j} {
! if {$j == 1} {set type "abc" }
! if {$j == 2} {set type "def" }
! if {$j == 3} {set type "hij" }
! if {$j == 4} {set type "lmn" }
! if {$j == 5} {set type "qrs" }
!
! puts "$j>$type"
!}
>
Provides access to expect send & expect commands:
!send "ls\n"
!expect -re "test" { puts "got test"} "rand2" { puts "got rand" } default {puts "got nothing"}
Embedded expect can fail the entire expect-lite script by calling the built-in _el_fail_test function:
!if { $arch == "ppc" } { 				
! puts "\narch IS $arch\n"
! } else {
! puts "\narch is NOT ppc, but $arch\n"
! _el_fail_test
! }
>
TCL files can be sourced, and functions can be declared and called from within embedded expect.

Limitations of Embedded Expect:

Please remember, this functionality is to provide assistance to expect-lite rather than replace it. (see What's Missing)

Examples of Expect-lite

Below are some examples to better illustrate what can be accomplished with expect-lite:

Setting the IP address on a secondary interface of the remote host (be sure to escape the dot's in the IP address)
$local_eth=eth1
$ip_addr=192\.168\.10\.2
# change timeout value to 10 sec
@10
>ifconfig $local_eth $ip_addr
#check to ensure that we set the right IP address
>ifconfig
<$ip_addr
Starting a telnet to another host
@2
>telnet remote-host-018
<login
>root
<assword
>secret_password
# issue a command once logged in
>pwd
>^]
>quit

Starting a ssh session to another host
>ssh root@host-021
<assword:
>secret_password
# issue a command once logged in
>ls
>exit

Use of 'screen' command to keep a command alive after test completes
; ==== Use Screen command for to keep application running ====
>screen
> $pmm
# Check that HW is alive
>ping
<Successfully pinged the PM H/W
; ==== Keep pmm application active, and detach from this screen
>^A
>^D
<detached
>
Assigning a dynamic variable $host using regex to capture the hostname from 'uname -a' command
>uname -a
+$host=Linux ([a-z\-0-9]+)
Assigned Var:host=remote-host-008
>
Assigning multiple dynamic variables using regex to capture environment variables $HOME and $SHELL, while expecting $TERM=xterm
>env | sort
+$home=\nHOME=([a-z/]+)
+$shell=\nSHELL=([a-z/]+)
<TERM=xterm
Assigned Var:home=/home/joe
Assigned Var:shell=/bin/bash
>
Manage multiple Screen commands with a dynamic variable and regex capture
# show the last screen in the list 
>screen -list | grep pts | sort | tail -1
# regex capture to dynamically assign the result to var $myscreen
+$myscreen=([0-9]+\.pts.[0-9]+.[a-z\- 0-9]+)
# connect to $myscreen
> screen -r $myscreen
# inside existing screen, kick it to get a prompt
>^M
> sleep 3
> ls
>
>^A
>^D
<detached
>
Using Regex in expect-lite to allow multiple responses
>id
# allow either groups users or wheel
<(users|wheel)
Create a temporary file with unique name including script name and date. The predefined variable $arg0 is contains the expect-lite script name.
# date stamp of script run time
>echo `date +_%Y_%m_%d_%H-%M-%S`
+$DATE=\n(_[0-9_-]+)

$temp_file=$arg0$DATE
; === Create a temp file using bash "here doc" method
>cat > $temp_file <<'+++'
>line 1
>line 2
>+++
>

Test Failure?!?

When will expect-lite fail a test? It will only fail a test when an expected result (after issuing a command) does not appear in the specified timeout period. For example in the following command file:
$ip_addr=192.168.10.99
>/sbin/ifconfig eth0 $ip_addr
>/sbin/ifconfig eth0
< $ip_addr
The first line will be sent (blindly), since there is no expected return. On line 3, the ifconfig command is sent again, and the script is looking for a desired result of  192.168.10.99 (using the var $ip_addr). If for some reason the ip address is different than ip address was returned, the script would fail.

Not Expect
A test can also fail should text appear that is unexpected (such as an error). This does not clear the expect input buffer, and should be used before a valid expect. How long should the script wait for the un-expected? In order to reduce delays in script running time, the Not Expect feature only waits for 100ms. This is usually enough time to detect quick error responses such as "file not found". 

For example: Fail device doesn't exist
>ls -l /dev/linux
-<No such file
In another example: We don't like Mondays
; === fail if today is 'Monday'
>date +%A
-<Monday
Since the expect input buffer is not consumed, valid expects can still be performed. in the following example, ttyS2 will still be found.
>ls -1 /dev/ttyS*
-<ttyX
<ttyS2
It is recommended that Not Expect lines be used before valid expect lines.

How can it help?

Expect-lite can be used to quickly create automated tests. It can collapse complicated tests into a single command line. It can also be used in nightly regression testing, performing simple functional tests providing confidence that core functionality has not been broken by the previous day's submissions.

Limitations


Expect-lite is limited to what a person could do in one (1) terminal window (or xterm). It cannot start a program in one window and run a different program in a separate window. Therefore it does not currently support multiple sessions. Using the Linux 'screen' command can assist in working around this limitation (see examples). 

Standard programming constructs such as looping and branching are now supported as of version 3.0.0. Real Expect can do these things and more. That said, looping is limited to a repeat loop and branching can be accomplished with Labels.

Expect-lite has been purposely limited to keep scripts simple, easy to use and maintain. Although more complex scripts can be created, basic expect-lite scripts can be created by simply cutting and pasting text from a terminal window into a script and adding '>' '<' characters.

Implementation Details

Variables

Variable names must be restricted to the following set of characters [A-Za-z0-9_]. Variable values may include spaces, and quoting is not required nor permitted. For example:
$bell=For whom the bell tolls
>echo $bell
For whom the bell tolls

Implied "wait for prompt"

Using the '>' character implies waiting for the prompt before sending the command. The definition of a shell prompt a: $, #, % or >. It is often useful to follow a '<' with a '>' for force the script to wait for the prompt:
> $some_long_command
<critical value
# wait for prompt
>
Prompt detection can be problematic, and by no means is expect-lite's method perfect. Expect-lite looks for a prompt character ($, #, % or >) followed by a space at the end of line. This should work for most standard prompts, however coloured or fancy prompts may not be detected. The function wait_for_prompt is provided near the top of expect-lite script for one to adapt to custom prompts.

It may be useful to create files on the fly which will be used in the test. Since expect-lite does not read/write files directly, this function can be done with the linux command 'cat' and the bash here doc method. Creating a regex file for example:
; ==== Create Test File on the fly
> cat > $regex_test_file << '+++'
>T00001/a(?$XL.*)/tag=0x08000001
>T00002/b(?$XR.*)/tag=0x08000002
>T00003/c(?$XO[0-7]*)/tag=0x08000003
>T00004/d(?$XH[0-9A-F]*)/tag=0x08000004
>T00005/e(?$XD[0-9]*)/tag=0x08000005
>+++
>
In the above example the script initiates a cat to a file (referenced by $regex_test_file ). Normally the '>' would be used to send lines to the remote host. However, there is an inherent "wait for prompt", which will politely wait for the next line. The last '>' is there to wait for the prompt to return after the cat command.

Predefined variables

Expect-lite has minimized the use of predefined variables to allow the user the widest latitude in selecting variable names. However a few predefined variables are useful and listed below:
Predefined variable
Usage
$arg0 expect-lite script name. Set to the c= or cmd_file= value. Useful for creating temporary files unique to the test script.
$timeout_multiplier Typically used as a constant (passed in from the command line) which the integer value is multiplied by each of the timeouts in the script. i.e. @10 x $timeout_muliplier = real timeout. The value default is 1.

Timeouts

Setting the expect-lite timeout to 0 isn't actually zero as this will cause the keyboard input buffer on the remote machine to overflow (and lose characters). Expect-lite adds a 50ms delay between lines when the @0 is used to prevent the overflow.

Expect Input Buffer

Expect by default places strings that are sent back (from the remote host) into an expect buffer ($expect_out(buffer)). Expect-lite leverages this built in function, and uses it to perform multiple searches through the buffer when using the '<' , '+<' or '-<' actions. The actions '>' and '>>' will clear expect buffer to prevent spurious matches.

Timing is everything: delay_wait_for_host

When communicating with a remote host, enough time must be provided for the remote host to respond. There is an internal global value of $delay_wait_for_host (in mili-seconds) which can be tuned to your environment. This value is also used by the Expect Not feature to determine how long Expect-Not should wait for the unexpected.

Unsynchronized messages disclaimer

Effort has been put into making the output as synchronous as possible. However because what is seen on stdout or screen is data returned/echoed from the remote host and printable comments are directly printed to stdout, it is possible to have a printable comment appear in the stdout before the action it references is returned from the remote host. This lack of synchronization can sometimes be minimized by adding an additional '>' after the printable comment as shown in the following:
; === starting long command
>
>start_long_command

What's missing

In order to maintain an easy-to-learn, simple-to-use expect like language, looping has been intentionally kept simple and intuitive. Most expect-lite scripts will be to be top down, single pass scripts, making the scripts easy to create and read. These limitations preserve the KISS principle.

If more complexity is required, consider using embedded expect inside expect-lite, or writing a native expect script.

Debugging Expect-lite Scripts

Expect-lite was written to permit quick and easy automation of repetitive tasks. However, sometimes a little additional debugging is required. Additional include scripts, debug.inc and show_vars.inc, have been added to the release (as of version 3.1.3) to assist in debugging scripts.

See the Tips and Techniques Guide for additional expect-lite script debugging information.

Why Expect-lite

Expect-lite was written so you don't have to learn expect. It provides a quick way to write simple expect scripts using just the > and < characters.

COPYING


Copyright (c) 2007, Freescale Semiconductor, Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the Freescale Semiconductor nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.



8 July 2008
http://expect-lite.sourceforge.net/

Subscribe to expect-list-users Discussion List

this document for version 3.1.3 and above