github.com/franono/tendermint@v0.32.2-0.20200527150959-749313264ce9/privval/signer_client_test.go (about)

     1  package privval
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/require"
    10  
    11  	tmrand "github.com/franono/tendermint/libs/rand"
    12  	"github.com/franono/tendermint/types"
    13  )
    14  
    15  type signerTestCase struct {
    16  	chainID      string
    17  	mockPV       types.PrivValidator
    18  	signerClient *SignerClient
    19  	signerServer *SignerServer
    20  }
    21  
    22  func getSignerTestCases(t *testing.T) []signerTestCase {
    23  	testCases := make([]signerTestCase, 0)
    24  
    25  	// Get test cases for each possible dialer (DialTCP / DialUnix / etc)
    26  	for _, dtc := range getDialerTestCases(t) {
    27  		chainID := tmrand.Str(12)
    28  		mockPV := types.NewMockPV()
    29  
    30  		// get a pair of signer listener, signer dialer endpoints
    31  		sl, sd := getMockEndpoints(t, dtc.addr, dtc.dialer)
    32  		sc, err := NewSignerClient(sl)
    33  		require.NoError(t, err)
    34  		ss := NewSignerServer(sd, chainID, mockPV)
    35  
    36  		err = ss.Start()
    37  		require.NoError(t, err)
    38  
    39  		tc := signerTestCase{
    40  			chainID:      chainID,
    41  			mockPV:       mockPV,
    42  			signerClient: sc,
    43  			signerServer: ss,
    44  		}
    45  
    46  		testCases = append(testCases, tc)
    47  	}
    48  
    49  	return testCases
    50  }
    51  
    52  func TestSignerClose(t *testing.T) {
    53  	for _, tc := range getSignerTestCases(t) {
    54  		err := tc.signerClient.Close()
    55  		assert.NoError(t, err)
    56  
    57  		err = tc.signerServer.Stop()
    58  		assert.NoError(t, err)
    59  	}
    60  }
    61  
    62  func TestSignerPing(t *testing.T) {
    63  	for _, tc := range getSignerTestCases(t) {
    64  		defer tc.signerServer.Stop()
    65  		defer tc.signerClient.Close()
    66  
    67  		err := tc.signerClient.Ping()
    68  		assert.NoError(t, err)
    69  	}
    70  }
    71  
    72  func TestSignerGetPubKey(t *testing.T) {
    73  	for _, tc := range getSignerTestCases(t) {
    74  		defer tc.signerServer.Stop()
    75  		defer tc.signerClient.Close()
    76  
    77  		pubKey, err := tc.signerClient.GetPubKey()
    78  		require.NoError(t, err)
    79  		expectedPubKey, err := tc.mockPV.GetPubKey()
    80  		require.NoError(t, err)
    81  
    82  		assert.Equal(t, expectedPubKey, pubKey)
    83  
    84  		pubKey, err = tc.signerClient.GetPubKey()
    85  		require.NoError(t, err)
    86  		expectedpk, err := tc.mockPV.GetPubKey()
    87  		require.NoError(t, err)
    88  		expectedAddr := expectedpk.Address()
    89  
    90  		assert.Equal(t, expectedAddr, pubKey.Address())
    91  	}
    92  }
    93  
    94  func TestSignerProposal(t *testing.T) {
    95  	for _, tc := range getSignerTestCases(t) {
    96  		ts := time.Now()
    97  		want := &types.Proposal{Timestamp: ts}
    98  		have := &types.Proposal{Timestamp: ts}
    99  
   100  		defer tc.signerServer.Stop()
   101  		defer tc.signerClient.Close()
   102  
   103  		require.NoError(t, tc.mockPV.SignProposal(tc.chainID, want))
   104  		require.NoError(t, tc.signerClient.SignProposal(tc.chainID, have))
   105  
   106  		assert.Equal(t, want.Signature, have.Signature)
   107  	}
   108  }
   109  
   110  func TestSignerVote(t *testing.T) {
   111  	for _, tc := range getSignerTestCases(t) {
   112  		ts := time.Now()
   113  		want := &types.Vote{Timestamp: ts, Type: types.PrecommitType}
   114  		have := &types.Vote{Timestamp: ts, Type: types.PrecommitType}
   115  
   116  		defer tc.signerServer.Stop()
   117  		defer tc.signerClient.Close()
   118  
   119  		require.NoError(t, tc.mockPV.SignVote(tc.chainID, want))
   120  		require.NoError(t, tc.signerClient.SignVote(tc.chainID, have))
   121  
   122  		assert.Equal(t, want.Signature, have.Signature)
   123  	}
   124  }
   125  
   126  func TestSignerVoteResetDeadline(t *testing.T) {
   127  	for _, tc := range getSignerTestCases(t) {
   128  		ts := time.Now()
   129  		want := &types.Vote{Timestamp: ts, Type: types.PrecommitType}
   130  		have := &types.Vote{Timestamp: ts, Type: types.PrecommitType}
   131  
   132  		defer tc.signerServer.Stop()
   133  		defer tc.signerClient.Close()
   134  
   135  		time.Sleep(testTimeoutReadWrite2o3)
   136  
   137  		require.NoError(t, tc.mockPV.SignVote(tc.chainID, want))
   138  		require.NoError(t, tc.signerClient.SignVote(tc.chainID, have))
   139  		assert.Equal(t, want.Signature, have.Signature)
   140  
   141  		// TODO(jleni): Clarify what is actually being tested
   142  
   143  		// This would exceed the deadline if it was not extended by the previous message
   144  		time.Sleep(testTimeoutReadWrite2o3)
   145  
   146  		require.NoError(t, tc.mockPV.SignVote(tc.chainID, want))
   147  		require.NoError(t, tc.signerClient.SignVote(tc.chainID, have))
   148  		assert.Equal(t, want.Signature, have.Signature)
   149  	}
   150  }
   151  
   152  func TestSignerVoteKeepAlive(t *testing.T) {
   153  	for _, tc := range getSignerTestCases(t) {
   154  		ts := time.Now()
   155  		want := &types.Vote{Timestamp: ts, Type: types.PrecommitType}
   156  		have := &types.Vote{Timestamp: ts, Type: types.PrecommitType}
   157  
   158  		defer tc.signerServer.Stop()
   159  		defer tc.signerClient.Close()
   160  
   161  		// Check that even if the client does not request a
   162  		// signature for a long time. The service is still available
   163  
   164  		// in this particular case, we use the dialer logger to ensure that
   165  		// test messages are properly interleaved in the test logs
   166  		tc.signerServer.Logger.Debug("TEST: Forced Wait -------------------------------------------------")
   167  		time.Sleep(testTimeoutReadWrite * 3)
   168  		tc.signerServer.Logger.Debug("TEST: Forced Wait DONE---------------------------------------------")
   169  
   170  		require.NoError(t, tc.mockPV.SignVote(tc.chainID, want))
   171  		require.NoError(t, tc.signerClient.SignVote(tc.chainID, have))
   172  
   173  		assert.Equal(t, want.Signature, have.Signature)
   174  	}
   175  }
   176  
   177  func TestSignerSignProposalErrors(t *testing.T) {
   178  	for _, tc := range getSignerTestCases(t) {
   179  		// Replace service with a mock that always fails
   180  		tc.signerServer.privVal = types.NewErroringMockPV()
   181  		tc.mockPV = types.NewErroringMockPV()
   182  
   183  		defer tc.signerServer.Stop()
   184  		defer tc.signerClient.Close()
   185  
   186  		ts := time.Now()
   187  		proposal := &types.Proposal{Timestamp: ts}
   188  		err := tc.signerClient.SignProposal(tc.chainID, proposal)
   189  		require.Equal(t, err.(*RemoteSignerError).Description, types.ErroringMockPVErr.Error())
   190  
   191  		err = tc.mockPV.SignProposal(tc.chainID, proposal)
   192  		require.Error(t, err)
   193  
   194  		err = tc.signerClient.SignProposal(tc.chainID, proposal)
   195  		require.Error(t, err)
   196  	}
   197  }
   198  
   199  func TestSignerSignVoteErrors(t *testing.T) {
   200  	for _, tc := range getSignerTestCases(t) {
   201  		ts := time.Now()
   202  		vote := &types.Vote{Timestamp: ts, Type: types.PrecommitType}
   203  
   204  		// Replace signer service privval with one that always fails
   205  		tc.signerServer.privVal = types.NewErroringMockPV()
   206  		tc.mockPV = types.NewErroringMockPV()
   207  
   208  		defer tc.signerServer.Stop()
   209  		defer tc.signerClient.Close()
   210  
   211  		err := tc.signerClient.SignVote(tc.chainID, vote)
   212  		require.Equal(t, err.(*RemoteSignerError).Description, types.ErroringMockPVErr.Error())
   213  
   214  		err = tc.mockPV.SignVote(tc.chainID, vote)
   215  		require.Error(t, err)
   216  
   217  		err = tc.signerClient.SignVote(tc.chainID, vote)
   218  		require.Error(t, err)
   219  	}
   220  }
   221  
   222  func brokenHandler(privVal types.PrivValidator, request SignerMessage, chainID string) (SignerMessage, error) {
   223  	var res SignerMessage
   224  	var err error
   225  
   226  	switch r := request.(type) {
   227  
   228  	// This is broken and will answer most requests with a pubkey response
   229  	case *PubKeyRequest:
   230  		res = &PubKeyResponse{nil, nil}
   231  	case *SignVoteRequest:
   232  		res = &PubKeyResponse{nil, nil}
   233  	case *SignProposalRequest:
   234  		res = &PubKeyResponse{nil, nil}
   235  
   236  	case *PingRequest:
   237  		err, res = nil, &PingResponse{}
   238  
   239  	default:
   240  		err = fmt.Errorf("unknown msg: %v", r)
   241  	}
   242  
   243  	return res, err
   244  }
   245  
   246  func TestSignerUnexpectedResponse(t *testing.T) {
   247  	for _, tc := range getSignerTestCases(t) {
   248  		tc.signerServer.privVal = types.NewMockPV()
   249  		tc.mockPV = types.NewMockPV()
   250  
   251  		tc.signerServer.SetRequestHandler(brokenHandler)
   252  
   253  		defer tc.signerServer.Stop()
   254  		defer tc.signerClient.Close()
   255  
   256  		ts := time.Now()
   257  		want := &types.Vote{Timestamp: ts, Type: types.PrecommitType}
   258  
   259  		e := tc.signerClient.SignVote(tc.chainID, want)
   260  		assert.EqualError(t, e, "received unexpected response")
   261  	}
   262  }