package privval
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/tendermint/tendermint/libs/common"
|
|
"github.com/tendermint/tendermint/types"
|
|
)
|
|
|
|
type signerTestCase struct {
|
|
chainID string
|
|
mockPV types.PrivValidator
|
|
signer *SignerClient
|
|
signerService *SignerDialerEndpoint
|
|
}
|
|
|
|
func getSignerTestCases(t *testing.T) []signerTestCase {
|
|
testCases := make([]signerTestCase, 0)
|
|
|
|
for _, dtc := range getDialerTestCases(t) {
|
|
chainID := common.RandStr(12)
|
|
mockPV := types.NewMockPV()
|
|
|
|
ve, se := getMockEndpoints(t, chainID, mockPV, dtc.addr, dtc.dialer)
|
|
sr, err := NewSignerClient(ve)
|
|
assert.NoError(t, err)
|
|
|
|
tc := signerTestCase{
|
|
chainID: chainID,
|
|
mockPV: mockPV,
|
|
signer: sr,
|
|
signerService: se,
|
|
}
|
|
|
|
testCases = append(testCases, tc)
|
|
break
|
|
}
|
|
|
|
return testCases
|
|
}
|
|
|
|
func TestSignerClose(t *testing.T) {
|
|
for _, tc := range getSignerTestCases(t) {
|
|
func() {
|
|
err := tc.signer.Close()
|
|
assert.NoError(t, err)
|
|
|
|
err = tc.signerService.Stop()
|
|
assert.NoError(t, err)
|
|
}()
|
|
}
|
|
}
|
|
|
|
func TestSignerGetPubKey(t *testing.T) {
|
|
for _, tc := range getSignerTestCases(t) {
|
|
func() {
|
|
defer tc.signerService.OnStop()
|
|
defer tc.signer.Close()
|
|
|
|
pubKey := tc.signer.GetPubKey()
|
|
expectedPubKey := tc.mockPV.GetPubKey()
|
|
|
|
assert.Equal(t, expectedPubKey, pubKey)
|
|
|
|
addr := tc.signer.GetPubKey().Address()
|
|
expectedAddr := tc.mockPV.GetPubKey().Address()
|
|
|
|
assert.Equal(t, expectedAddr, addr)
|
|
}()
|
|
}
|
|
}
|
|
|
|
func TestSignerProposal(t *testing.T) {
|
|
for _, tc := range getSignerTestCases(t) {
|
|
func() {
|
|
ts := time.Now()
|
|
want := &types.Proposal{Timestamp: ts}
|
|
have := &types.Proposal{Timestamp: ts}
|
|
|
|
defer tc.signerService.OnStop()
|
|
defer tc.signer.Close()
|
|
|
|
require.NoError(t, tc.mockPV.SignProposal(tc.chainID, want))
|
|
require.NoError(t, tc.signer.SignProposal(tc.chainID, have))
|
|
|
|
assert.Equal(t, want.Signature, have.Signature)
|
|
}()
|
|
}
|
|
}
|
|
|
|
func TestSignerVote(t *testing.T) {
|
|
for _, tc := range getSignerTestCases(t) {
|
|
func() {
|
|
ts := time.Now()
|
|
want := &types.Vote{Timestamp: ts, Type: types.PrecommitType}
|
|
have := &types.Vote{Timestamp: ts, Type: types.PrecommitType}
|
|
|
|
defer tc.signerService.OnStop()
|
|
defer tc.signer.Close()
|
|
|
|
require.NoError(t, tc.mockPV.SignVote(tc.chainID, want))
|
|
require.NoError(t, tc.signer.SignVote(tc.chainID, have))
|
|
|
|
assert.Equal(t, want.Signature, have.Signature)
|
|
}()
|
|
}
|
|
}
|
|
|
|
func TestSignerVoteResetDeadline(t *testing.T) {
|
|
for _, tc := range getSignerTestCases(t) {
|
|
func() {
|
|
ts := time.Now()
|
|
want := &types.Vote{Timestamp: ts, Type: types.PrecommitType}
|
|
have := &types.Vote{Timestamp: ts, Type: types.PrecommitType}
|
|
|
|
defer tc.signerService.OnStop()
|
|
defer tc.signer.Close()
|
|
|
|
time.Sleep(testTimeoutReadWrite2o3)
|
|
|
|
require.NoError(t, tc.mockPV.SignVote(tc.chainID, want))
|
|
require.NoError(t, tc.signer.SignVote(tc.chainID, have))
|
|
assert.Equal(t, want.Signature, have.Signature)
|
|
|
|
// TODO(jleni): Clarify what is actually being tested
|
|
|
|
// This would exceed the deadline if it was not extended by the previous message
|
|
time.Sleep(testTimeoutReadWrite2o3)
|
|
|
|
require.NoError(t, tc.mockPV.SignVote(tc.chainID, want))
|
|
require.NoError(t, tc.signer.SignVote(tc.chainID, have))
|
|
assert.Equal(t, want.Signature, have.Signature)
|
|
}()
|
|
}
|
|
}
|
|
|
|
func TestSignerVoteKeepAlive(t *testing.T) {
|
|
for _, tc := range getSignerTestCases(t) {
|
|
func() {
|
|
ts := time.Now()
|
|
want := &types.Vote{Timestamp: ts, Type: types.PrecommitType}
|
|
have := &types.Vote{Timestamp: ts, Type: types.PrecommitType}
|
|
|
|
defer tc.signerService.OnStop()
|
|
defer tc.signer.Close()
|
|
|
|
// Check that even if the client does not request a
|
|
// signature for a long time. The service is will available
|
|
tc.signerService.Logger.Info("TEST. Forced Wait")
|
|
time.Sleep(testTimeoutReadWrite * 2)
|
|
tc.signerService.Logger.Info("TEST. Forced Wait - DONE")
|
|
|
|
require.NoError(t, tc.mockPV.SignVote(tc.chainID, want))
|
|
require.NoError(t, tc.signer.SignVote(tc.chainID, have))
|
|
|
|
assert.Equal(t, want.Signature, have.Signature)
|
|
}()
|
|
}
|
|
}
|
|
|
|
func TestSignerSignProposalErrors(t *testing.T) {
|
|
for _, tc := range getSignerTestCases(t) {
|
|
func() {
|
|
// Replace service with a mock that always fails
|
|
tc.signerService.privVal = types.NewErroringMockPV()
|
|
tc.mockPV = types.NewErroringMockPV()
|
|
|
|
defer tc.signerService.OnStop()
|
|
defer tc.signer.Close()
|
|
|
|
//ts := time.Now()
|
|
//proposal := &types.Proposal{Timestamp: ts}
|
|
//err := tc.signer.SignProposal(tc.chainID, proposal)
|
|
//require.Equal(t, err.(*RemoteSignerError).Description, types.ErroringMockPVErr.Error())
|
|
//
|
|
//err = tc.mockPV.SignProposal(tc.chainID, proposal)
|
|
//require.Error(t, err)
|
|
//
|
|
//err = tc.signer.SignProposal(tc.chainID, proposal)
|
|
//require.Error(t, err)
|
|
}()
|
|
}
|
|
}
|
|
|
|
func TestSignerSignVoteErrors(t *testing.T) {
|
|
for _, tc := range getSignerTestCases(t) {
|
|
func() {
|
|
ts := time.Now()
|
|
vote := &types.Vote{Timestamp: ts, Type: types.PrecommitType}
|
|
|
|
// Replace signer service privval with one that always fails
|
|
tc.signerService.privVal = types.NewErroringMockPV()
|
|
tc.mockPV = types.NewErroringMockPV()
|
|
|
|
defer tc.signerService.OnStop()
|
|
defer tc.signer.Close()
|
|
|
|
err := tc.signer.SignVote(tc.chainID, vote)
|
|
require.Equal(t, err.(*RemoteSignerError).Description, types.ErroringMockPVErr.Error())
|
|
|
|
err = tc.mockPV.SignVote(tc.chainID, vote)
|
|
require.Error(t, err)
|
|
|
|
err = tc.signer.SignVote(tc.chainID, vote)
|
|
require.Error(t, err)
|
|
}()
|
|
}
|
|
}
|
|
|
|
type BrokenSignerDialerEndpoint struct {
|
|
*SignerDialerEndpoint
|
|
}
|
|
|
|
func (ss *BrokenSignerDialerEndpoint) writeMessage(msg RemoteSignerMsg) (err error) {
|
|
_, err = cdc.MarshalBinaryLengthPrefixedWriter(ss.conn, PubKeyResponse{})
|
|
return
|
|
}
|
|
|
|
func TestSignerUnexpectedResponse(t *testing.T) {
|
|
for _, tc := range getSignerTestCases(t) {
|
|
func() {
|
|
// TODO(jleni): This test is actually not working. Fails for a different reason
|
|
|
|
tc.signerService.privVal = types.NewErroringMockPV()
|
|
tc.mockPV = types.NewErroringMockPV()
|
|
|
|
// Replace signer service with a broken one
|
|
tc.signerService.OnStop()
|
|
tmp := BrokenSignerDialerEndpoint{tc.signerService}
|
|
tmp.OnStart()
|
|
|
|
defer tmp.OnStop()
|
|
defer tc.signer.Close()
|
|
|
|
ts := time.Now()
|
|
want := &types.Vote{Timestamp: ts, Type: types.PrecommitType}
|
|
|
|
e := tc.signer.SignVote(tc.chainID, want)
|
|
println(e.Error())
|
|
require.Error(t, e)
|
|
}()
|
|
}
|
|
}
|