github.com/evdatsion/aphelion-dpos-bft@v0.32.1/tools/tm-signer-harness/internal/test_harness_test.go (about) 1 package internal 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "net" 7 "os" 8 "testing" 9 "time" 10 11 "github.com/evdatsion/aphelion-dpos-bft/crypto" 12 "github.com/evdatsion/aphelion-dpos-bft/privval" 13 "github.com/evdatsion/aphelion-dpos-bft/types" 14 15 "github.com/stretchr/testify/assert" 16 "github.com/stretchr/testify/require" 17 "github.com/evdatsion/aphelion-dpos-bft/crypto/ed25519" 18 "github.com/evdatsion/aphelion-dpos-bft/libs/log" 19 ) 20 21 const ( 22 keyFileContents = `{ 23 "address": "D08FCA3BA74CF17CBFC15E64F9505302BB0E2748", 24 "pub_key": { 25 "type": "tendermint/PubKeyEd25519", 26 "value": "ZCsuTjaczEyon70nmKxwvwu+jqrbq5OH3yQjcK0SFxc=" 27 }, 28 "priv_key": { 29 "type": "tendermint/PrivKeyEd25519", 30 "value": "8O39AkQsoe1sBQwud/Kdul8lg8K9SFsql9aZvwXQSt1kKy5ONpzMTKifvSeYrHC/C76Oqturk4ffJCNwrRIXFw==" 31 } 32 }` 33 34 stateFileContents = `{ 35 "height": "0", 36 "round": "0", 37 "step": 0 38 }` 39 40 genesisFileContents = `{ 41 "genesis_time": "2019-01-15T11:56:34.8963Z", 42 "chain_id": "test-chain-0XwP5E", 43 "consensus_params": { 44 "block": { 45 "max_bytes": "22020096", 46 "max_gas": "-1", 47 "time_iota_ms": "1000" 48 }, 49 "evidence": { 50 "max_age": "100000" 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.SignerServiceEndpoint { 89 return newMockRemoteSigner(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.SignerServiceEndpoint { 99 return newMockRemoteSigner(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.SignerServiceEndpoint { 109 return newMockRemoteSigner(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.SignerServiceEndpoint { 119 return newMockRemoteSigner(t, th, th.fpv.Key.PrivKey, false, true) 120 }, 121 ErrTestSignVoteFailed, 122 ) 123 } 124 125 func newMockRemoteSigner(t *testing.T, th *TestHarness, privKey crypto.PrivKey, breakProposalSigning bool, breakVoteSigning bool) *privval.SignerServiceEndpoint { 126 return privval.NewSignerServiceEndpoint( 127 th.logger, 128 th.chainID, 129 types.NewMockPVWithParams(privKey, breakProposalSigning, breakVoteSigning), 130 privval.DialTCPFn( 131 th.addr, 132 time.Duration(defaultConnDeadline)*time.Millisecond, 133 ed25519.GenPrivKey(), 134 ), 135 ) 136 } 137 138 // For running relatively standard tests. 139 func harnessTest(t *testing.T, rsMaker func(th *TestHarness) *privval.SignerServiceEndpoint, expectedExitCode int) { 140 cfg := makeConfig(t, 100, 3) 141 defer cleanup(cfg) 142 143 th, err := NewTestHarness(log.TestingLogger(), cfg) 144 require.NoError(t, err) 145 donec := make(chan struct{}) 146 go func() { 147 defer close(donec) 148 th.Run() 149 }() 150 151 rs := rsMaker(th) 152 require.NoError(t, rs.Start()) 153 assert.True(t, rs.IsRunning()) 154 defer rs.Stop() 155 156 <-donec 157 assert.Equal(t, expectedExitCode, th.exitCode) 158 } 159 160 func makeConfig(t *testing.T, acceptDeadline, acceptRetries int) TestHarnessConfig { 161 return TestHarnessConfig{ 162 BindAddr: testFreeTCPAddr(t), 163 KeyFile: makeTempFile("tm-testharness-keyfile", keyFileContents), 164 StateFile: makeTempFile("tm-testharness-statefile", stateFileContents), 165 GenesisFile: makeTempFile("tm-testharness-genesisfile", genesisFileContents), 166 AcceptDeadline: time.Duration(acceptDeadline) * time.Millisecond, 167 ConnDeadline: time.Duration(defaultConnDeadline) * time.Millisecond, 168 AcceptRetries: acceptRetries, 169 SecretConnKey: ed25519.GenPrivKey(), 170 ExitWhenComplete: false, 171 } 172 } 173 174 func cleanup(cfg TestHarnessConfig) { 175 os.Remove(cfg.KeyFile) 176 os.Remove(cfg.StateFile) 177 os.Remove(cfg.GenesisFile) 178 } 179 180 func makeTempFile(name, content string) string { 181 tempFile, err := ioutil.TempFile("", fmt.Sprintf("%s-*", name)) 182 if err != nil { 183 panic(err) 184 } 185 if _, err := tempFile.Write([]byte(content)); err != nil { 186 tempFile.Close() 187 panic(err) 188 } 189 if err := tempFile.Close(); err != nil { 190 panic(err) 191 } 192 return tempFile.Name() 193 } 194 195 // testFreeTCPAddr claims a free port so we don't block on listener being ready. 196 func testFreeTCPAddr(t *testing.T) string { 197 ln, err := net.Listen("tcp", "127.0.0.1:0") 198 require.NoError(t, err) 199 defer ln.Close() 200 201 return fmt.Sprintf("127.0.0.1:%d", ln.Addr().(*net.TCPAddr).Port) 202 }