github.com/ari-anchor/sei-tendermint@v0.0.0-20230519144642-dc826b7b56bb/cmd/tendermint/commands/reindex_event_test.go (about) 1 package commands 2 3 import ( 4 "context" 5 "errors" 6 "testing" 7 8 "github.com/spf13/cobra" 9 "github.com/stretchr/testify/mock" 10 "github.com/stretchr/testify/require" 11 12 dbm "github.com/tendermint/tm-db" 13 14 abcitypes "github.com/ari-anchor/sei-tendermint/abci/types" 15 "github.com/ari-anchor/sei-tendermint/config" 16 "github.com/ari-anchor/sei-tendermint/internal/state/indexer" 17 "github.com/ari-anchor/sei-tendermint/internal/state/mocks" 18 "github.com/ari-anchor/sei-tendermint/libs/log" 19 "github.com/ari-anchor/sei-tendermint/types" 20 21 _ "github.com/lib/pq" // for the psql sink 22 ) 23 24 const ( 25 height int64 = 10 26 base int64 = 2 27 ) 28 29 func setupReIndexEventCmd(ctx context.Context, conf *config.Config, logger log.Logger) *cobra.Command { 30 cmd := MakeReindexEventCommand(conf, logger) 31 32 reIndexEventCmd := &cobra.Command{ 33 Use: cmd.Use, 34 Run: func(cmd *cobra.Command, args []string) {}, 35 } 36 37 _ = reIndexEventCmd.ExecuteContext(ctx) 38 39 return reIndexEventCmd 40 } 41 42 func TestReIndexEventCheckHeight(t *testing.T) { 43 mockBlockStore := &mocks.BlockStore{} 44 mockBlockStore. 45 On("Base").Return(base). 46 On("Height").Return(height) 47 48 testCases := []struct { 49 startHeight int64 50 endHeight int64 51 validHeight bool 52 }{ 53 {0, 0, true}, 54 {0, base, true}, 55 {0, base - 1, false}, 56 {0, height, true}, 57 {0, height + 1, true}, 58 {0, 0, true}, 59 {base - 1, 0, false}, 60 {base, 0, true}, 61 {base, base, true}, 62 {base, base - 1, false}, 63 {base, height, true}, 64 {base, height + 1, true}, 65 {height, 0, true}, 66 {height, base, false}, 67 {height, height - 1, false}, 68 {height, height, true}, 69 {height, height + 1, true}, 70 {height + 1, 0, false}, 71 } 72 73 for _, tc := range testCases { 74 err := checkValidHeight(mockBlockStore, checkValidHeightArgs{startHeight: tc.startHeight, endHeight: tc.endHeight}) 75 if tc.validHeight { 76 require.NoError(t, err) 77 } else { 78 require.Error(t, err) 79 } 80 } 81 } 82 83 func TestLoadEventSink(t *testing.T) { 84 testCases := []struct { 85 sinks []string 86 connURL string 87 loadErr bool 88 }{ 89 {[]string{}, "", true}, 90 {[]string{"NULL"}, "", true}, 91 {[]string{"KV"}, "", false}, 92 {[]string{"KV", "KV"}, "", true}, 93 {[]string{"PSQL"}, "", true}, // true because empty connect url 94 {[]string{"PSQL"}, "wrongUrl", true}, // true because wrong connect url 95 // skip to test PSQL connect with correct url 96 {[]string{"UnsupportedSinkType"}, "wrongUrl", true}, 97 } 98 99 for _, tc := range testCases { 100 cfg := config.TestConfig() 101 cfg.TxIndex.Indexer = tc.sinks 102 cfg.TxIndex.PsqlConn = tc.connURL 103 _, err := loadEventSinks(cfg) 104 if tc.loadErr { 105 require.Error(t, err) 106 } else { 107 require.NoError(t, err) 108 } 109 } 110 } 111 112 func TestLoadBlockStore(t *testing.T) { 113 testCfg, err := config.ResetTestRoot(t.TempDir(), t.Name()) 114 require.NoError(t, err) 115 testCfg.DBBackend = "goleveldb" 116 _, _, err = loadStateAndBlockStore(testCfg) 117 // we should return an error because the state store and block store 118 // don't yet exist 119 require.Error(t, err) 120 121 dbType := dbm.BackendType(testCfg.DBBackend) 122 bsdb, err := dbm.NewDB("blockstore", dbType, testCfg.DBDir()) 123 require.NoError(t, err) 124 bsdb.Close() 125 126 ssdb, err := dbm.NewDB("state", dbType, testCfg.DBDir()) 127 require.NoError(t, err) 128 ssdb.Close() 129 130 bs, ss, err := loadStateAndBlockStore(testCfg) 131 require.NoError(t, err) 132 require.NotNil(t, bs) 133 require.NotNil(t, ss) 134 } 135 136 func TestReIndexEvent(t *testing.T) { 137 mockBlockStore := &mocks.BlockStore{} 138 mockStateStore := &mocks.Store{} 139 mockEventSink := &mocks.EventSink{} 140 141 mockBlockStore. 142 On("Base").Return(base). 143 On("Height").Return(height). 144 On("LoadBlock", base).Return(nil).Once(). 145 On("LoadBlock", base).Return(&types.Block{Data: types.Data{Txs: types.Txs{make(types.Tx, 1)}}}). 146 On("LoadBlock", height).Return(&types.Block{Data: types.Data{Txs: types.Txs{make(types.Tx, 1)}}}) 147 148 mockEventSink. 149 On("Type").Return(indexer.KV). 150 On("IndexBlockEvents", mock.AnythingOfType("types.EventDataNewBlockHeader")).Return(errors.New("")).Once(). 151 On("IndexBlockEvents", mock.AnythingOfType("types.EventDataNewBlockHeader")).Return(nil). 152 On("IndexTxEvents", mock.AnythingOfType("[]*types.TxResult")).Return(errors.New("")).Once(). 153 On("IndexTxEvents", mock.AnythingOfType("[]*types.TxResult")).Return(nil) 154 155 dtx := abcitypes.ExecTxResult{} 156 abciResp := &abcitypes.ResponseFinalizeBlock{ 157 TxResults: []*abcitypes.ExecTxResult{&dtx}, 158 } 159 160 mockStateStore. 161 On("LoadFinalizeBlockResponses", base).Return(nil, errors.New("")).Once(). 162 On("LoadFinalizeBlockResponses", base).Return(abciResp, nil). 163 On("LoadFinalizeBlockResponses", height).Return(abciResp, nil) 164 165 testCases := []struct { 166 startHeight int64 167 endHeight int64 168 reIndexErr bool 169 }{ 170 {base, height, true}, // LoadBlock error 171 {base, height, true}, // LoadFinalizeBlockResponses error 172 {base, height, true}, // index block event error 173 {base, height, true}, // index tx event error 174 {base, base, false}, 175 {height, height, false}, 176 } 177 178 ctx, cancel := context.WithCancel(context.Background()) 179 defer cancel() 180 logger := log.NewNopLogger() 181 conf := config.DefaultConfig() 182 183 for _, tc := range testCases { 184 err := eventReIndex( 185 setupReIndexEventCmd(ctx, conf, logger), 186 eventReIndexArgs{ 187 sinks: []indexer.EventSink{mockEventSink}, 188 blockStore: mockBlockStore, 189 stateStore: mockStateStore, 190 startHeight: tc.startHeight, 191 endHeight: tc.endHeight, 192 }) 193 194 if tc.reIndexErr { 195 require.Error(t, err) 196 } else { 197 require.NoError(t, err) 198 } 199 } 200 }