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"))) }