github.com/okex/exchain@v1.8.0/libs/tendermint/node/node_test.go (about) 1 package node 2 3 import ( 4 "context" 5 "fmt" 6 "net" 7 "os" 8 "syscall" 9 "testing" 10 "time" 11 12 "github.com/stretchr/testify/assert" 13 "github.com/stretchr/testify/require" 14 15 dbm "github.com/okex/exchain/libs/tm-db" 16 17 "github.com/okex/exchain/libs/tendermint/abci/example/kvstore" 18 cfg "github.com/okex/exchain/libs/tendermint/config" 19 "github.com/okex/exchain/libs/tendermint/crypto/ed25519" 20 "github.com/okex/exchain/libs/tendermint/evidence" 21 "github.com/okex/exchain/libs/tendermint/libs/log" 22 tmrand "github.com/okex/exchain/libs/tendermint/libs/rand" 23 mempl "github.com/okex/exchain/libs/tendermint/mempool" 24 "github.com/okex/exchain/libs/tendermint/p2p" 25 p2pmock "github.com/okex/exchain/libs/tendermint/p2p/mock" 26 "github.com/okex/exchain/libs/tendermint/privval" 27 "github.com/okex/exchain/libs/tendermint/proxy" 28 sm "github.com/okex/exchain/libs/tendermint/state" 29 "github.com/okex/exchain/libs/tendermint/types" 30 tmtime "github.com/okex/exchain/libs/tendermint/types/time" 31 "github.com/okex/exchain/libs/tendermint/version" 32 ) 33 34 func TestNodeStartStop(t *testing.T) { 35 config := cfg.ResetTestRoot("node_node_test") 36 defer os.RemoveAll(config.RootDir) 37 38 // create & start node 39 n, err := DefaultNewNode(config, log.TestingLogger()) 40 require.NoError(t, err) 41 err = n.Start() 42 require.NoError(t, err) 43 44 t.Logf("Started node %v", n.sw.NodeInfo()) 45 46 // wait for the node to produce a block 47 blocksSub, err := n.EventBus().Subscribe(context.Background(), "node_test", types.EventQueryNewBlock) 48 require.NoError(t, err) 49 select { 50 case <-blocksSub.Out(): 51 case <-blocksSub.Cancelled(): 52 t.Fatal("blocksSub was cancelled") 53 case <-time.After(10 * time.Second): 54 t.Fatal("timed out waiting for the node to produce a block") 55 } 56 57 // stop the node 58 go func() { 59 n.Stop() 60 }() 61 62 select { 63 case <-n.Quit(): 64 case <-time.After(5 * time.Second): 65 pid := os.Getpid() 66 p, err := os.FindProcess(pid) 67 if err != nil { 68 panic(err) 69 } 70 err = p.Signal(syscall.SIGABRT) 71 fmt.Println(err) 72 t.Fatal("timed out waiting for shutdown") 73 } 74 } 75 76 func TestSplitAndTrimEmpty(t *testing.T) { 77 testCases := []struct { 78 s string 79 sep string 80 cutset string 81 expected []string 82 }{ 83 {"a,b,c", ",", " ", []string{"a", "b", "c"}}, 84 {" a , b , c ", ",", " ", []string{"a", "b", "c"}}, 85 {" a, b, c ", ",", " ", []string{"a", "b", "c"}}, 86 {" a, ", ",", " ", []string{"a"}}, 87 {" ", ",", " ", []string{}}, 88 } 89 90 for _, tc := range testCases { 91 assert.Equal(t, tc.expected, splitAndTrimEmpty(tc.s, tc.sep, tc.cutset), "%s", tc.s) 92 } 93 } 94 95 func TestNodeDelayedStart(t *testing.T) { 96 config := cfg.ResetTestRoot("node_delayed_start_test") 97 defer os.RemoveAll(config.RootDir) 98 now := tmtime.Now() 99 100 config.Instrumentation.Prometheus = false 101 // create & start node 102 n, err := DefaultNewNode(config, log.TestingLogger()) 103 n.GenesisDoc().GenesisTime = now.Add(2 * time.Second) 104 require.NoError(t, err) 105 106 err = n.Start() 107 require.NoError(t, err) 108 defer n.Stop() 109 110 startTime := tmtime.Now() 111 assert.Equal(t, true, startTime.After(n.GenesisDoc().GenesisTime)) 112 } 113 114 func TestNodeSetAppVersion(t *testing.T) { 115 config := cfg.ResetTestRoot("node_app_version_test") 116 defer os.RemoveAll(config.RootDir) 117 118 config.Instrumentation.Prometheus = false 119 // create & start node 120 n, err := DefaultNewNode(config, log.TestingLogger()) 121 require.NoError(t, err) 122 123 // default config uses the kvstore app 124 var appVersion version.Protocol = kvstore.ProtocolVersion 125 126 // check version is set in state 127 state := sm.LoadState(n.stateDB) 128 assert.Equal(t, state.Version.Consensus.App, appVersion) 129 130 // check version is set in node info 131 assert.Equal(t, n.nodeInfo.(p2p.DefaultNodeInfo).ProtocolVersion.App, appVersion) 132 } 133 134 func TestNodeSetPrivValTCP(t *testing.T) { 135 addr := "tcp://" + testFreeAddr(t) 136 137 config := cfg.ResetTestRoot("node_priv_val_tcp_test") 138 defer os.RemoveAll(config.RootDir) 139 config.BaseConfig.PrivValidatorListenAddr = addr 140 141 dialer := privval.DialTCPFn(addr, 100*time.Millisecond, ed25519.GenPrivKey()) 142 dialerEndpoint := privval.NewSignerDialerEndpoint( 143 log.TestingLogger(), 144 dialer, 145 ) 146 privval.SignerDialerEndpointTimeoutReadWrite(100 * time.Millisecond)(dialerEndpoint) 147 148 signerServer := privval.NewSignerServer( 149 dialerEndpoint, 150 config.ChainID(), 151 types.NewMockPV(), 152 ) 153 154 go func() { 155 err := signerServer.Start() 156 if err != nil { 157 panic(err) 158 } 159 }() 160 defer signerServer.Stop() 161 162 config.Instrumentation.Prometheus = false 163 n, err := DefaultNewNode(config, log.TestingLogger()) 164 require.NoError(t, err) 165 assert.IsType(t, &privval.RetrySignerClient{}, n.PrivValidator()) 166 } 167 168 // address without a protocol must result in error 169 func TestPrivValidatorListenAddrNoProtocol(t *testing.T) { 170 addrNoPrefix := testFreeAddr(t) 171 172 config := cfg.ResetTestRoot("node_priv_val_tcp_test") 173 defer os.RemoveAll(config.RootDir) 174 config.BaseConfig.PrivValidatorListenAddr = addrNoPrefix 175 176 _, err := DefaultNewNode(config, log.TestingLogger()) 177 assert.Error(t, err) 178 } 179 180 func TestNodeSetPrivValIPC(t *testing.T) { 181 tmpfile := "/tmp/kms." + tmrand.Str(6) + ".sock" 182 defer os.Remove(tmpfile) // clean up 183 184 config := cfg.ResetTestRoot("node_priv_val_tcp_test") 185 defer os.RemoveAll(config.RootDir) 186 config.BaseConfig.PrivValidatorListenAddr = "unix://" + tmpfile 187 188 dialer := privval.DialUnixFn(tmpfile) 189 dialerEndpoint := privval.NewSignerDialerEndpoint( 190 log.TestingLogger(), 191 dialer, 192 ) 193 privval.SignerDialerEndpointTimeoutReadWrite(100 * time.Millisecond)(dialerEndpoint) 194 195 pvsc := privval.NewSignerServer( 196 dialerEndpoint, 197 config.ChainID(), 198 types.NewMockPV(), 199 ) 200 201 go func() { 202 err := pvsc.Start() 203 require.NoError(t, err) 204 }() 205 defer pvsc.Stop() 206 207 config.Instrumentation.Prometheus = false 208 n, err := DefaultNewNode(config, log.TestingLogger()) 209 require.NoError(t, err) 210 assert.IsType(t, &privval.RetrySignerClient{}, n.PrivValidator()) 211 } 212 213 // testFreeAddr claims a free port so we don't block on listener being ready. 214 func testFreeAddr(t *testing.T) string { 215 ln, err := net.Listen("tcp", "127.0.0.1:0") 216 require.NoError(t, err) 217 defer ln.Close() 218 219 return fmt.Sprintf("127.0.0.1:%d", ln.Addr().(*net.TCPAddr).Port) 220 } 221 222 // create a proposal block using real and full 223 // mempool and evidence pool and validate it. 224 func TestCreateProposalBlock(t *testing.T) { 225 config := cfg.ResetTestRoot("node_create_proposal") 226 defer os.RemoveAll(config.RootDir) 227 config.Instrumentation.Prometheus = false 228 cc := proxy.NewLocalClientCreator(kvstore.NewApplication()) 229 proxyApp := proxy.NewAppConns(cc) 230 err := proxyApp.Start() 231 require.Nil(t, err) 232 defer proxyApp.Stop() 233 234 logger := log.TestingLogger() 235 236 var height int64 = 1 237 state, stateDB := state(1, height) 238 maxBytes := 16384 239 state.ConsensusParams.Block.MaxBytes = int64(maxBytes) 240 proposerAddr, _ := state.Validators.GetByIndex(0) 241 242 // Make Mempool 243 memplMetrics := mempl.PrometheusMetrics("node_test") 244 mempool := mempl.NewCListMempool( 245 config.Mempool, 246 proxyApp.Mempool(), 247 state.LastBlockHeight, 248 mempl.WithMetrics(memplMetrics), 249 mempl.WithPreCheck(sm.TxPreCheck(state)), 250 mempl.WithPostCheck(sm.TxPostCheck(state)), 251 ) 252 mempool.SetLogger(logger) 253 254 // Make EvidencePool 255 types.RegisterMockEvidencesGlobal() // XXX! 256 evidence.RegisterMockEvidences() 257 evidenceDB := dbm.NewMemDB() 258 evidencePool := evidence.NewPool(stateDB, evidenceDB) 259 evidencePool.SetLogger(logger) 260 261 // fill the evidence pool with more evidence 262 // than can fit in a block 263 minEvSize := 12 264 numEv := (maxBytes / types.MaxEvidenceBytesDenominator) / minEvSize 265 for i := 0; i < numEv; i++ { 266 ev := types.NewMockRandomEvidence(1, time.Now(), proposerAddr, tmrand.Bytes(minEvSize)) 267 err := evidencePool.AddEvidence(ev) 268 assert.NoError(t, err) 269 } 270 271 // fill the mempool with more txs 272 // than can fit in a block 273 txLength := 1000 274 for i := 0; i < maxBytes/txLength; i++ { 275 tx := tmrand.Bytes(txLength) 276 err := mempool.CheckTx(tx, nil, mempl.TxInfo{}) 277 assert.NoError(t, err) 278 } 279 280 blockExec := sm.NewBlockExecutor( 281 stateDB, 282 logger, 283 proxyApp.Consensus(), 284 mempool, 285 evidencePool, 286 ) 287 288 commit := types.NewCommit(height-1, 0, types.BlockID{}, nil) 289 block, _ := blockExec.CreateProposalBlock( 290 height, 291 state, commit, 292 proposerAddr, 293 ) 294 295 err = blockExec.ValidateBlock(state, block) 296 assert.NoError(t, err) 297 } 298 299 func TestNodeNewNodeCustomReactors(t *testing.T) { 300 config := cfg.ResetTestRoot("node_new_node_custom_reactors_test") 301 defer os.RemoveAll(config.RootDir) 302 config.Instrumentation.Prometheus = false 303 304 cr := p2pmock.NewReactor() 305 customBlockchainReactor := p2pmock.NewReactor() 306 307 nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) 308 require.NoError(t, err) 309 310 n, err := NewNode(config, 311 privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()), 312 nodeKey, 313 proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()), 314 DefaultGenesisDocProviderFunc(config), 315 DefaultDBProvider, 316 DefaultMetricsProvider(config.Instrumentation), 317 log.TestingLogger(), 318 CustomReactors(map[string]p2p.Reactor{"FOO": cr, "BLOCKCHAIN": customBlockchainReactor}), 319 ) 320 require.NoError(t, err) 321 322 err = n.Start() 323 require.NoError(t, err) 324 defer n.Stop() 325 326 assert.True(t, cr.IsRunning()) 327 assert.Equal(t, cr, n.Switch().Reactor("FOO")) 328 329 assert.True(t, customBlockchainReactor.IsRunning()) 330 assert.Equal(t, customBlockchainReactor, n.Switch().Reactor("BLOCKCHAIN")) 331 } 332 333 func state(nVals int, height int64) (sm.State, dbm.DB) { 334 vals := make([]types.GenesisValidator, nVals) 335 for i := 0; i < nVals; i++ { 336 secret := []byte(fmt.Sprintf("test%d", i)) 337 pk := ed25519.GenPrivKeyFromSecret(secret) 338 vals[i] = types.GenesisValidator{ 339 Address: pk.PubKey().Address(), 340 PubKey: pk.PubKey(), 341 Power: 1000, 342 Name: fmt.Sprintf("test%d", i), 343 } 344 } 345 s, _ := sm.MakeGenesisState(&types.GenesisDoc{ 346 ChainID: "test-chain", 347 Validators: vals, 348 AppHash: nil, 349 }) 350 351 // save validators to db for 2 heights 352 stateDB := dbm.NewMemDB() 353 sm.SaveState(stateDB, s) 354 355 for i := 1; i < int(height); i++ { 356 s.LastBlockHeight++ 357 s.LastValidators = s.Validators.Copy() 358 sm.SaveState(stateDB, s) 359 } 360 return s, stateDB 361 }