go-expect icon indicating copy to clipboard operation
go-expect copied to clipboard

ExpectString panics

Open psparago opened this issue 5 years ago • 3 comments

I'm just getting started with go-expect and I'm having difficulty getting a simple test to work. I'm not sure where else to post this because it's not really an issue, it's more of a request for help.

In my test app, I am spawning the Linux SSH client and sending commands. I need to capture the full output that was generated as I will parse through that later.

The issue I'm having is with the ExpectString calls. I get a panic when Expect() calls c.runeReader.ReadRune() (line 89) in bufio.go ReadRune() that the index of an input buffer that is used is out of range. (If I replace the Expects with sleeps, the whole thing works has expected).

Here's my code (sensitive info removed) and I don't know why the markdown is messed up: ` func expectations() { f, _ := os.Create("/tmp/log.log") defer f.Close()

l := log.New(f, "logger: ", log.Lshortfile)

buf := new(bytes.Buffer)

c, err := expect.NewConsole(expect.WithStdout(os.Stdout), expect.WithStdout(buf), expect.WithLogger(l))
if err != nil {
	logit(err.Error())
	os.Exit(1)
}
defer c.Close()

cmd := exec.Command("bash", "-c", "sshpass -p 'topsecret' ssh -p 22 -o 'StrictHostKeyChecking no'  [email protected]")
cmd.Stdin = c.Tty()
cmd.Stdout = c.Tty()
cmd.Stderr = c.Tty()

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

err = cmd.Start()
if err != nil {
	logit(err.Error())
	os.Exit(1)
}

count := 0
var e error
var s string
count, e = c.SendLine("")
logit(fmt.Sprintf("send: %d - %+v", count, e))
s, e = c.ExpectString("prompt#")
logit(fmt.Sprintf("expect: %s - %+v", s, e))
count, e = c.SendLine("some command")
logit(fmt.Sprintf("send: %d - %+v", count, e))
s, e = c.ExpectString("prompt#")
logit(fmt.Sprintf("expect: %s - %+v", s, e))
count, e = c.SendLine("another command")
logit(fmt.Sprintf("send: %d - %+v", count, e))
s, e = c.ExpectString("prompt#")
logit(fmt.Sprintf("expect: %s - %+v", s, e))
count, e = c.SendLine("logout")
logit(fmt.Sprintf("send: %d - %+v", count, e))
s, e = c.ExpectString("Logoff")
logit(fmt.Sprintf("expect: %s - %+v", s, e))

err = cmd.Wait()
if err != nil {
	logit(err.Error())
	//os.Exit(1)
}

logit(fmt.Sprintf("\n\n----------------------------------\n%s\n", buf.String()))

} `

And the output (cleaned up). Note that the string of hashtags is a banner from the server:

send: 1 - /n

###############################panic: runtime error: index out of range

goroutine 20 [running]: bufio.(*Reader).ReadRune(0xc000116240, 0x2, 0x2, 0x0, 0x6a75a0) /usr/lib/golang/src/bufio/bufio.go:279 +0x257 github.com/Netflix/go-expect.(*Console).Expect(0xc0001140c0, 0xc000037780, 0x2, 0x2, 0x0, 0x0, 0x0, 0x0) /home/device42/gocode/src/github.com/Netflix/go-expect/expect.go:89 +0x257 github.com/Netflix/go-expect.(*Console).ExpectEOF(0xc0001140c0, 0x0, 0x0, 0x0, 0x0) /home/device42/gocode/src/github.com/Netflix/go-expect/expect.go:41 +0x6b main.expectations.func1(0xc0001140c0) /home/device42/gocode/go-gadgets/src/test/test.go:97 +0x2b created by main.expectations /home/device42/gocode/go-gadgets/src/test/test.go:96 +0x33d

I don't understand why the deferred c.ExpectEOF() is executing at this point.

Any ideas?

Thanks.

psparago avatar May 13 '20 23:05 psparago

Hi @psparago, so the problem here is that you're calling c.ExpectEOF in a goroutine at the same time as calling other c.ExpectString, etc. I think what you want is to remove that goroutine and move that c.ExpectEOF after c.ExpectString("Logoff").

On our side, we'll need to fix that panic.

hinshun avatar May 14 '20 00:05 hinshun

Hi @hinshun, Thank you sooo much for the immediate response. Moving the ExpectEOF worked! (That's what I get for copying an example I really didn't understand).

By we'll need to fix that panic, I assume you mean that if a dunderhead like me does what I did again, the package won't panic? In other words, I do not need to wait for a release of the package, is that correct?

psparago avatar May 14 '20 00:05 psparago

It's not your fault, I think we're lacking documentation for this package. And yes, you don't need to wait for a new release, we should just have a better error message for this scenario.

hinshun avatar May 14 '20 01:05 hinshun