Expect.jl allows to spawn interactive applications and control them by communicating through their standard input/output streams.
Expect.jl is similar to D. Libes’s Expect and many other Expect-like modules. It can be used to automate interactive applications such as shells, perform software testing or drive test harnesses easily.
This is a work-in-progress, the API is subject to change without notice. Suggestions about API design are highly appeciated.
Releases are ephemeral at the time of writing. Julia 0.3 is supported, but all development is performed with Julia 0.4.
All the relevant source/developer information can be found on Gitlab:
The idea behind Expect is simple: commands are spawned with their I/O descriptors attached to the current process. You write to the command’s standard input, then you wait for a set of known replies from it’s output.
If the program you’re communicating with was already meant to be controlled through a serial protocol, then using readandwrite directly is recommended as it avoids some overhead when spawning the process.
Expect differs from readandwrite in two major ways:
Using ftp to retrieve a remote file list:
julia> # Start a new process julia> using Expect; julia> proc = ExpectProc(`ftp ftp.scene.org`, 16); julia> # Wait for the prompt julia> expect!(proc, "> "); julia> # Send "ls" and wait for prompt julia> sendline(proc, "ls"); julia> expect!(proc, "> "); julia> # Collect all the output since the last prompt julia> list = proc.before; julia> println(list); drwxrwsr-x 11 redhound ftpadm 4096 Mar 2 20:57 incoming drwx------ 2 redhound ftpadm 16384 Feb 24 12:58 lost+found -rw-r--r-- 1 redhound ftpadm 16060223 Mar 22 01:15 ls-lR -rw-r--r-- 1 redhound ftpadm 2723919 Mar 22 01:15 ls-lR.gz drwxrwsr-x 12 redhound ftpadm 4096 Nov 26 2013 mirrors drwxrwsr-x 8 redhound ftpadm 4096 Mar 4 18:25 pub -rw-r--r-- 1 redhound ftpadm 547 Nov 9 2013 welcome.msg
Some highlights about the example:
The last point can be clarified with the following example:
julia> using Expect; julia> proc = ExpectProc(`echo "a b c "`, 16); julia> expect!(proc, " ") "a" julia> expect!(proc, " ") "b" julia> expect!(proc, " ") "c"
For convenience, expect! already returns the contents of proc.before when given a single pattern to match.
expect! however is normally used with a list of possible matches to perform. In this scenario, the index that matched first will be returned. The matched string itself is also available in proc.match. This is useful to perform conditional processing depending on the command’s output:
using Expect proc = ExpectProc(`interpreter`, 16) sendline(proc, "perform") idx = expect!(proc, ["> ", "ERROR: "]) if idx == 2 # error occurred ... end
See tests/runtests.jl for more usage examples.
ExpectProc(cmd, timeout; env, codec):
Write string to the standard input of the program, followed by a newline.
expect!(proc, vector; timeout):
Read the standard output of the program until one of the strings/regular expressions specified in vector matches. The index of the element that matched first is returned. Matches are searched in sequential order.
When timeout is specified, it overrides the default timeout specified in the constructor.
proc.before is reset at each call to contain all the standard output before the match.
proc.match contains either a string or a match object for the element that matched.
expect!(proc, element; timeout):
Read the standard output of the program until the string/regular expressions specified in element matches. The content of proc.before is returned.