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 }