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  }