package privval
|
|
|
|
import (
|
|
"net"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/tendermint/tendermint/crypto/ed25519"
|
|
cmn "github.com/tendermint/tendermint/libs/common"
|
|
"github.com/tendermint/tendermint/libs/log"
|
|
"github.com/tendermint/tendermint/types"
|
|
)
|
|
|
|
// TestRemoteSignerRetryTCPOnly will test connection retry attempts over TCP. We
|
|
// don't need this for Unix sockets because the OS instantly knows the state of
|
|
// both ends of the socket connection. This basically causes the
|
|
// RemoteSigner.dialer() call inside RemoteSigner.connect() to return
|
|
// successfully immediately, putting an instant stop to any retry attempts.
|
|
func TestRemoteSignerRetryTCPOnly(t *testing.T) {
|
|
var (
|
|
attemptc = make(chan int)
|
|
retries = 2
|
|
)
|
|
|
|
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
|
require.NoError(t, err)
|
|
|
|
go func(ln net.Listener, attemptc chan<- int) {
|
|
attempts := 0
|
|
|
|
for {
|
|
conn, err := ln.Accept()
|
|
require.NoError(t, err)
|
|
|
|
err = conn.Close()
|
|
require.NoError(t, err)
|
|
|
|
attempts++
|
|
|
|
if attempts == retries {
|
|
attemptc <- attempts
|
|
break
|
|
}
|
|
}
|
|
}(ln, attemptc)
|
|
|
|
rs := NewRemoteSigner(
|
|
log.TestingLogger(),
|
|
cmn.RandStr(12),
|
|
types.NewMockPV(),
|
|
DialTCPFn(ln.Addr().String(), testConnDeadline, ed25519.GenPrivKey()),
|
|
)
|
|
defer rs.Stop()
|
|
|
|
RemoteSignerConnDeadline(time.Millisecond)(rs)
|
|
RemoteSignerConnRetries(retries)(rs)
|
|
|
|
assert.Equal(t, rs.Start(), ErrDialRetryMax)
|
|
|
|
select {
|
|
case attempts := <-attemptc:
|
|
assert.Equal(t, retries, attempts)
|
|
case <-time.After(100 * time.Millisecond):
|
|
t.Error("expected remote to observe connection attempts")
|
|
}
|
|
}
|
|
|
|
func TestIsConnTimeoutForFundamentalTimeouts(t *testing.T) {
|
|
// Generate a networking timeout
|
|
dialer := DialTCPFn(testFreeTCPAddr(t), time.Millisecond, ed25519.GenPrivKey())
|
|
_, err := dialer()
|
|
assert.Error(t, err)
|
|
assert.True(t, IsConnTimeout(err))
|
|
}
|
|
|
|
func TestIsConnTimeoutForWrappedConnTimeouts(t *testing.T) {
|
|
dialer := DialTCPFn(testFreeTCPAddr(t), time.Millisecond, ed25519.GenPrivKey())
|
|
_, err := dialer()
|
|
assert.Error(t, err)
|
|
err = cmn.ErrorWrap(ErrConnTimeout, err.Error())
|
|
assert.True(t, IsConnTimeout(err))
|
|
}
|
|
|
|
func TestIsConnTimeoutForNonTimeoutErrors(t *testing.T) {
|
|
assert.False(t, IsConnTimeout(cmn.ErrorWrap(ErrDialRetryMax, "max retries exceeded")))
|
|
assert.False(t, IsConnTimeout(errors.New("completely irrelevant error")))
|
|
}
|