Skip to content

Commit

Permalink
Allow caller to await and evaluate command completion (addresses leem…
Browse files Browse the repository at this point in the history
  • Loading branch information
Gerrit Renker authored and Gerrit Renker committed Oct 31, 2016
1 parent 8198930 commit 2e010fa
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 32 deletions.
21 changes: 8 additions & 13 deletions expect.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ line is:
}
exp.Send(EOF)
result, err := return exp.Wait()
fmt.Println("Command result:", result, err)
This package has only been tested on Linux
*/
package expect
Expand Down Expand Up @@ -114,19 +117,11 @@ type Expect struct {
// On EOF being read from Cmd this is set (and ExpectReader is ended)
Eof bool

// Result is filled in asynchronously after the cmd exits
Result ExpectWaitResult

// Cancellation context: @cancel causes internal and os/exec cancellation
ctx context.Context
cancel context.CancelFunc
}

type ExpectWaitResult struct {
ProcessState *os.ProcessState
Error error
}

// debugf logs only if Debug is true
func debugf(format string, args ...interface{}) {
if Debug {
Expand Down Expand Up @@ -167,7 +162,6 @@ func NewExpectContext(parentCtx context.Context, prog string, arg ...string) (ex
if exp.File, err = pty.Start(exp.cmd); err != nil {
return nil, err
}
go exp.expectReaper()

// make the pty non blocking so when I read from it I dont jam up
if err = syscall.SetNonblock(int(exp.File.Fd()), true); err != nil {
Expand All @@ -181,10 +175,11 @@ func NewExpectContext(parentCtx context.Context, prog string, arg ...string) (ex
return exp, nil
}

// expectReaper reaps the process if it ends for any reason and saves the
// Wait() result
func (exp *Expect) expectReaper() {
exp.Result.ProcessState, exp.Result.Error = exp.cmd.Process.Wait()
// Wait() reaps the command process and returns its resulting process state.
// If the command terminated due to context cancellation, error will be one of
// the package constants context.Canceled or context.Deadline.
func (exp *Expect) Wait() (*os.ProcessState, error) {
return exp.cmd.Process.Wait()
}

// SetCmdOut if a non-nil io.Writer is passed it will be sent a copy of everything
Expand Down
24 changes: 5 additions & 19 deletions expect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,27 +82,13 @@ func checkResultRe(t *testing.T, pat string, re *regexp.Regexp, i int, n int, fo
}
}

// showWaitResults awaits command completion, and prints the resulting process state
func showWaitResult(t *testing.T, exp *Expect) {
// Wait a little bit for Result to be filled in
time.Sleep(time.Millisecond * 10)
// Try a few fimes to see if its valid (maybe I should have used a channel
// but checking for all the errors is painful for code I expect to be used
// so rarely)
for i := 1; i <= 3; i++ {
if exp.Result.ProcessState != nil {
break
}
t.Logf("pause %d for Wait() result", i)
time.Sleep(time.Second)
}
if exp.Result.ProcessState == nil {
t.Logf("Wait() result never went valid")
return
}
if exp.Result.Error != nil {
t.Logf("Wait() result: %s, %s", exp.Result.ProcessState, exp.Result.Error)
processState, err := exp.Wait()
if err != nil {
t.Logf("Wait() error result: %s, %s", processState, err)
} else {
t.Logf("Wait() result: %s", exp.Result.ProcessState)
t.Logf("Wait() result: %s", processState)
}
}

Expand Down

0 comments on commit 2e010fa

Please sign in to comment.