Skip to content

Commit

Permalink
Merge pull request #207 from kdisneur/v1.3.3_fix
Browse files Browse the repository at this point in the history
Fix sendinput hanging forever when connection is blocked
  • Loading branch information
carlmontanari authored Dec 16, 2024
2 parents cb04adc + 83f5204 commit 69f1f0b
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 6 deletions.
3 changes: 2 additions & 1 deletion channel/channel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func prepareChannel(
t *testing.T,
testName,
payloadFile string,
chanOpts ...util.Option,
) (*channel.Channel, *transport.File) {
l, _ := logging.NewInstance()

Expand All @@ -90,7 +91,7 @@ func prepareChannel(
t.Errorf("%s: encountered error creating File Transport, error: %s", testName, err)
}

c, err := channel.NewChannel(l, transportObj)
c, err := channel.NewChannel(l, transportObj, chanOpts...)
if err != nil {
t.Errorf("%s: encountered error creating Channel, error: %s", testName, err)
}
Expand Down
16 changes: 14 additions & 2 deletions channel/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,20 @@ func (c *Channel) ReadAll() ([]byte, error) {
}

// ReadUntilFuzzy reads until a fuzzy match of the input is found.
func (c *Channel) ReadUntilFuzzy(b []byte) ([]byte, error) {
func (c *Channel) ReadUntilFuzzy(ctx context.Context, b []byte) ([]byte, error) {
if len(b) == 0 {
return nil, nil
}

var rb []byte

for {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}

nb, err := c.Read()
if err != nil {
return nil, err
Expand All @@ -193,10 +199,16 @@ func (c *Channel) ReadUntilFuzzy(b []byte) ([]byte, error) {

// ReadUntilExplicit reads bytes out of the channel Q object until the bytes b are seen in the
// output. Once the bytes are seen all read bytes are returned.
func (c *Channel) ReadUntilExplicit(b []byte) ([]byte, error) {
func (c *Channel) ReadUntilExplicit(ctx context.Context, b []byte) ([]byte, error) {
var rb []byte

for {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}

nb, err := c.Read()
if err != nil {
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion channel/sendinput.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (c *Channel) SendInputB(input []byte, opts ...util.Option) ([]byte, error)
return
}

_, err = readUntilF(input)
_, err = readUntilF(ctx, input)
if err != nil {
cr <- &result{b: b, err: err}

Expand Down
29 changes: 29 additions & 0 deletions channel/sendinput_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import (
"bytes"
"fmt"
"testing"
"time"

"github.com/scrapli/scrapligo/driver/opoptions"
"github.com/scrapli/scrapligo/driver/options"

"github.com/scrapli/scrapligo/util"

Expand Down Expand Up @@ -132,3 +134,30 @@ func TestSendInput(t *testing.T) {
t.Run(testName, f)
}
}

func TestSendCommandTimeout(t *testing.T) {
input := readFile(t, "send-input-timeout-in.txt")

c, _ := prepareChannel(
t,
t.Name(),
"send-input-timeout-out.txt",
options.WithTimeoutOps(1*time.Millisecond),
)
_, err := c.SendInput(string(input))

if err == nil {
t.Fatalf("%s: expecting an error but got none", t.Name())
}

expectedErr := "errTimeoutError: channel timeout sending input to device"

if err.Error() != expectedErr {
t.Fatalf(
"%s: actual and expected errors do not match\nactual: %s\nexpected:%s",
t.Name(),
err.Error(),
expectedErr,
)
}
}
4 changes: 2 additions & 2 deletions channel/sendinteractive.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func (c *Channel) sendInteractive(
cr chan *result,
events []*SendInteractiveEvent,
op *OperationOptions,
readUntilF func(b []byte) ([]byte, error),
readUntilF func(ctx context.Context, b []byte) ([]byte, error),
) {
defer close(cr)

Expand All @@ -48,7 +48,7 @@ func (c *Channel) sendInteractive(
if e.ChannelResponse != "" && !e.HideInput {
var nb []byte

nb, err = readUntilF([]byte(e.ChannelInput))
nb, err = readUntilF(ctx, []byte(e.ChannelInput))
if err != nil {
cr <- &result{b: nil, err: err}

Expand Down
1 change: 1 addition & 0 deletions channel/test-fixtures/send-input-timeout-in.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
show running-config
3 changes: 3 additions & 0 deletions channel/test-fixtures/send-input-timeout-out.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
RP/0/RP0/CPU0:iosxr75#terminal width 512
RP/0/RP0/CPU0:iosxr75#terminal length 0
RP/0/RP0/CPU0:iosxr75#show running-co

0 comments on commit 69f1f0b

Please sign in to comment.