github.com/vipernet-xyz/tm@v0.34.24/tools/tm-signer-harness/internal/test_harness_test.go (about) 1 package internal 2 3 import ( 4 "fmt" 5 "os" 6 "testing" 7 "time" 8 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/require" 11 12 "github.com/vipernet-xyz/tm/crypto" 13 "github.com/vipernet-xyz/tm/crypto/ed25519" 14 "github.com/vipernet-xyz/tm/libs/log" 15 "github.com/vipernet-xyz/tm/privval" 16 "github.com/vipernet-xyz/tm/types" 17 ) 18 19 const ( 20 keyFileContents = `{ 21 "address": "D08FCA3BA74CF17CBFC15E64F9505302BB0E2748", 22 "pub_key": { 23 "type": "tendermint/PubKeyEd25519", 24 "value": "ZCsuTjaczEyon70nmKxwvwu+jqrbq5OH3yQjcK0SFxc=" 25 }, 26 "priv_key": { 27 "type": "tendermint/PrivKeyEd25519", 28 "value": "8O39AkQsoe1sBQwud/Kdul8lg8K9SFsql9aZvwXQSt1kKy5ONpzMTKifvSeYrHC/C76Oqturk4ffJCNwrRIXFw==" 29 } 30 }` 31 32 stateFileContents = `{ 33 "height": "0", 34 "round": 0, 35 "step": 0 36 }` 37 38 genesisFileContents = `{ 39 "genesis_time": "2019-01-15T11:56:34.8963Z", 40 "chain_id": "test-chain-0XwP5E", 41 "consensus_params": { 42 "block": { 43 "max_bytes": "22020096", 44 "max_gas": "-1", 45 "time_iota_ms": "1000" 46 }, 47 "evidence": { 48 "max_age_num_blocks": "100000", 49 "max_age_duration": "172800000000000", 50 "max_num": 50 51 }, 52 "validator": { 53 "pub_key_types": [ 54 "ed25519" 55 ] 56 } 57 }, 58 "validators": [ 59 { 60 "address": "D08FCA3BA74CF17CBFC15E64F9505302BB0E2748", 61 "pub_key": { 62 "type": "tendermint/PubKeyEd25519", 63 "value": "ZCsuTjaczEyon70nmKxwvwu+jqrbq5OH3yQjcK0SFxc=" 64 }, 65 "power": "10", 66 "name": "" 67 } 68 ], 69 "app_hash": "" 70 }` 71 72 defaultConnDeadline = 100 73 ) 74 75 func TestRemoteSignerTestHarnessMaxAcceptRetriesReached(t *testing.T) { 76 cfg := makeConfig(t, 1, 2) 77 defer cleanup(cfg) 78 79 th, err := NewTestHarness(log.TestingLogger(), cfg) 80 require.NoError(t, err) 81 th.Run() 82 assert.Equal(t, ErrMaxAcceptRetriesReached, th.exitCode) 83 } 84 85 func TestRemoteSignerTestHarnessSuccessfulRun(t *testing.T) { 86 harnessTest( 87 t, 88 func(th *TestHarness) *privval.SignerServer { 89 return newMockSignerServer(t, th, th.fpv.Key.PrivKey, false, false) 90 }, 91 NoError, 92 ) 93 } 94 95 func TestRemoteSignerPublicKeyCheckFailed(t *testing.T) { 96 harnessTest( 97 t, 98 func(th *TestHarness) *privval.SignerServer { 99 return newMockSignerServer(t, th, ed25519.GenPrivKey(), false, false) 100 }, 101 ErrTestPublicKeyFailed, 102 ) 103 } 104 105 func TestRemoteSignerProposalSigningFailed(t *testing.T) { 106 harnessTest( 107 t, 108 func(th *TestHarness) *privval.SignerServer { 109 return newMockSignerServer(t, th, th.fpv.Key.PrivKey, true, false) 110 }, 111 ErrTestSignProposalFailed, 112 ) 113 } 114 115 func TestRemoteSignerVoteSigningFailed(t *testing.T) { 116 harnessTest( 117 t, 118 func(th *TestHarness) *privval.SignerServer { 119 return newMockSignerServer(t, th, th.fpv.Key.PrivKey, false, true) 120 }, 121 ErrTestSignVoteFailed, 122 ) 123 } 124 125 func newMockSignerServer( 126 t *testing.T, 127 th *TestHarness, 128 privKey crypto.PrivKey, 129 breakProposalSigning bool, 130 breakVoteSigning bool, 131 ) *privval.SignerServer { 132 mockPV := types.NewMockPVWithParams(privKey, breakProposalSigning, breakVoteSigning) 133 134 dialerEndpoint := privval.NewSignerDialerEndpoint( 135 th.logger, 136 privval.DialTCPFn( 137 th.addr, 138 time.Duration(defaultConnDeadline)*time.Millisecond, 139 ed25519.GenPrivKey(), 140 ), 141 ) 142 143 return privval.NewSignerServer(dialerEndpoint, th.chainID, mockPV) 144 } 145 146 // For running relatively standard tests. 147 func harnessTest(t *testing.T, signerServerMaker func(th *TestHarness) *privval.SignerServer, expectedExitCode int) { 148 cfg := makeConfig(t, 100, 3) 149 defer cleanup(cfg) 150 151 th, err := NewTestHarness(log.TestingLogger(), cfg) 152 require.NoError(t, err) 153 donec := make(chan struct{}) 154 go func() { 155 defer close(donec) 156 th.Run() 157 }() 158 159 ss := signerServerMaker(th) 160 require.NoError(t, ss.Start()) 161 assert.True(t, ss.IsRunning()) 162 defer ss.Stop() //nolint:errcheck // ignore for tests 163 164 <-donec 165 assert.Equal(t, expectedExitCode, th.exitCode) 166 } 167 168 func makeConfig(t *testing.T, acceptDeadline, acceptRetries int) TestHarnessConfig { 169 return TestHarnessConfig{ 170 BindAddr: privval.GetFreeLocalhostAddrPort(), 171 KeyFile: makeTempFile("tm-testharness-keyfile", keyFileContents), 172 StateFile: makeTempFile("tm-testharness-statefile", stateFileContents), 173 GenesisFile: makeTempFile("tm-testharness-genesisfile", genesisFileContents), 174 AcceptDeadline: time.Duration(acceptDeadline) * time.Millisecond, 175 ConnDeadline: time.Duration(defaultConnDeadline) * time.Millisecond, 176 AcceptRetries: acceptRetries, 177 SecretConnKey: ed25519.GenPrivKey(), 178 ExitWhenComplete: false, 179 } 180 } 181 182 func cleanup(cfg TestHarnessConfig) { 183 os.Remove(cfg.KeyFile) 184 os.Remove(cfg.StateFile) 185 os.Remove(cfg.GenesisFile) 186 } 187 188 func makeTempFile(name, content string) string { 189 tempFile, err := os.CreateTemp("", fmt.Sprintf("%s-*", name)) 190 if err != nil { 191 panic(err) 192 } 193 if _, err := tempFile.Write([]byte(content)); err != nil { 194 tempFile.Close() 195 panic(err) 196 } 197 if err := tempFile.Close(); err != nil { 198 panic(err) 199 } 200 return tempFile.Name() 201 }