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