expect

package module
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 1, 2020 License: Apache-2.0 Imports: 17 Imported by: 2

README

go-expect

Package expect provides an expect-like interface to automate control of applications. It is unlike expect in that it does not spawn or manage process lifecycle. This package only focuses on expecting output and sending input through it's pseudoterminal.

This is a fork of the original repository Netflix/go-expect mostly to add Windows support. This fork has been added to test the ActiveState state tool

Relevant additions:

  • Windows support (Windows 10 and Windows Sever 2019 only)
  • expect.Console is created with xpty allowing testing of applications that want to talk to an xterm-compatible terminal
  • Filter out VT control characters in output. This is important for Windows support, as the windows pseudo-console creates lots of control-characters that can break up words.

See also ActiveState/termtest for a library that uses this package, but adds more life-cycle management.

Usage

os.Exec example
package main

import (
	"log"
	"os"
	"os/exec"
	"time"

	"github.com/ActiveState/termtest/expect"
)

func main() {
	c, err := expect.NewConsole(expect.WithStdout(os.Stdout))
	if err != nil {
		log.Fatal(err)
	}
	defer c.Close()

	cmd := exec.Command("vi")
	cmd.Stdin = c.Tty()
	cmd.Stdout = c.Tty()
	cmd.Stderr = c.Tty()

	go func() {
		c.ExpectEOF()
	}()

	err = cmd.Start()
	if err != nil {
		log.Fatal(err)
	}

	time.Sleep(time.Second)
	c.Send("iHello world\x1b")
	time.Sleep(time.Second)
	c.Send("dd")
	time.Sleep(time.Second)
	c.SendLine(":q!")

	err = cmd.Wait()
	if err != nil {
		log.Fatal(err)
	}
}
golang.org/x/crypto/ssh/terminal example
package main

import (
	"fmt"

	"golang.org/x/crypto/ssh/terminal"

	"github.com/ActiveState/termtest/expect"
)

func getPassword(fd int) string {
	bytePassword, _ := terminal.ReadPassword(fd)

	return string(bytePassword)
}

func main() {
	c, _ := expect.NewConsole()

	defer c.Close()

	donec := make(chan struct{})
	go func() {
		defer close(donec)
		c.SendLine("hunter2")
	}()

	echoText := getPassword(int(c.Tty().Fd()))

	<-donec

	fmt.Printf("\nPassword from stdin: %s", echoText)
}

Documentation

Overview

Package expect provides an expect-like interface to automate control of applications. It is unlike expect in that it does not spawn or manage process lifecycle. This package only focuses on expecting output and sending input through it's psuedoterminal.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func EOF

func EOF(opts *ExpectOpts) error

EOF adds an Expect condition to exit if io.EOF is returned from reading Console's tty.

func NewTestWriter

func NewTestWriter(t *testing.T) (io.Writer, error)

NewTestWriter returns an io.Writer where bytes written to the file are logged by go's testing logger. Bytes are flushed to the logger on line end.

func PTSClosed

func PTSClosed(opts *ExpectOpts) error

PTSClosed adds an Expect condition to exit if we get an "read /dev/ptmx: input/output error" error which can occur on Linux while reading from the ptm after the pts is closed. Further Reading: https://github.com/kr/pty/issues/21#issuecomment-129381749

func StdinClosed

func StdinClosed(opts *ExpectOpts) error

StdinClosed adds an Expect condition to exit if we read from stdin after it has been closed which can occur on Windows while reading from the Pseudo-terminal after it is closed

func StripTrailingEmptyLines

func StripTrailingEmptyLines(out string) string

StripTrailingEmptyLines returns a copy of s stripped of trailing lines that consist of only space characters.

Types

type CallbackMatcher

type CallbackMatcher interface {
	// Callback executes the matcher's callback with the terminal state at the
	// time of match.
	Callback(matchState *MatchState) error
}

CallbackMatcher is a matcher that provides a Callback function.

type Console

type Console struct {
	Pty        *xpty.Xpty
	MatchState *MatchState
	// contains filtered or unexported fields
}

Console is an interface to automate input and output for interactive applications. Console can block until a specified output is received and send input back on it's tty. Console can also multiplex other sources of input and multiplex its output to other writers.

func NewConsole

func NewConsole(opts ...ConsoleOpt) (*Console, error)

NewConsole returns a new Console with the given options.

func NewTestConsole

func NewTestConsole(t *testing.T, opts ...ConsoleOpt) (*Console, error)

NewTestConsole returns a new Console that multiplexes the application's stdout to go's testing logger. Primarily so that outputs from parallel tests using t.Parallel() is not interleaved.

func (*Console) Close

func (c *Console) Close() error

Close closes both the TTY and afterwards all the readers You may want to split this up to give the readers time to read all the data until they reach the EOF error

func (*Console) CloseReaders

func (c *Console) CloseReaders() (err error)

CloseReaders closes everything that is trying to read from the terminal Call this function once you are sure that you have consumed all bytes

func (*Console) Expect

func (c *Console) Expect(opts ...ExpectOpt) (string, error)

Expect reads from Console's tty until a condition specified from opts is encountered or an error occurs, and returns the buffer read by console. No extra bytes are read once a condition is met, so if a program isn't expecting input yet, it will be blocked. Sends are queued up in tty's internal buffer so that the next Expect will read the remaining bytes (i.e. rest of prompt) as well as its conditions.

func (*Console) ExpectEOF

func (c *Console) ExpectEOF() (string, error)

ExpectEOF reads from Console's tty until EOF or an error occurs, and returns the buffer read by Console. We also treat the PTSClosed error as an EOF.

func (*Console) ExpectLongString added in v0.5.6

func (c *Console) ExpectLongString(s string) (string, error)

ExpectLongString reads from Console's tty until the provided long string is read or an error occurs, and returns the buffer read by Console. This function ignores mismatches caused by newline and space characters to account for wrappings at the maximum terminal width.

func (*Console) ExpectString

func (c *Console) ExpectString(s string) (string, error)

ExpectString reads from Console's tty until the provided string is read or an error occurs, and returns the buffer read by Console.

func (*Console) Expectf

func (c *Console) Expectf(format string, args ...interface{}) (string, error)

Expectf reads from the Console's tty until the provided formatted string is read or an error occurs, and returns the buffer read by Console.

func (*Console) Fd

func (c *Console) Fd() uintptr

Fd returns Console's file descripting referencing the master part of its pty.

func (*Console) Log

func (c *Console) Log(v ...interface{})

Log prints to Console's logger. Arguments are handled in the manner of fmt.Print.

func (*Console) Logf

func (c *Console) Logf(format string, v ...interface{})

Logf prints to Console's logger. Arguments are handled in the manner of fmt.Printf.

func (*Console) Send

func (c *Console) Send(s string) (int, error)

Send writes string s to Console's tty.

func (*Console) SendLine

func (c *Console) SendLine(s string) (int, error)

SendLine writes string s to Console's tty with a trailing newline.

func (*Console) SendOSLine added in v0.7.0

func (c *Console) SendOSLine(s string) (int, error)

SendOSLine writes string s to Console's tty with a trailing newline separator native to the base OS.

func (*Console) Tty

func (c *Console) Tty() *os.File

Tty returns Console's pts (slave part of a pty). A pseudoterminal, or pty is a pair of pseudo-devices, one of which, the slave, emulates a real text terminal device.

func (*Console) Write