github.com/number571/tendermint@v0.34.11-gost/state/indexer/indexer_service_test.go (about) 1 package indexer_test 2 3 import ( 4 "database/sql" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "testing" 9 "time" 10 11 "github.com/adlio/schema" 12 _ "github.com/lib/pq" 13 dockertest "github.com/ory/dockertest" 14 "github.com/ory/dockertest/docker" 15 "github.com/stretchr/testify/assert" 16 "github.com/stretchr/testify/require" 17 18 abci "github.com/number571/tendermint/abci/types" 19 tmlog "github.com/number571/tendermint/libs/log" 20 indexer "github.com/number571/tendermint/state/indexer" 21 kv "github.com/number571/tendermint/state/indexer/sink/kv" 22 psql "github.com/number571/tendermint/state/indexer/sink/psql" 23 "github.com/number571/tendermint/types" 24 db "github.com/tendermint/tm-db" 25 ) 26 27 var psqldb *sql.DB 28 var resource *dockertest.Resource 29 var pSink indexer.EventSink 30 31 var ( 32 user = "postgres" 33 password = "secret" 34 port = "5432" 35 dsn = "postgres://%s:%s@localhost:%s/%s?sslmode=disable" 36 dbName = "postgres" 37 ) 38 39 func TestIndexerServiceIndexesBlocks(t *testing.T) { 40 // event bus 41 eventBus := types.NewEventBus() 42 eventBus.SetLogger(tmlog.TestingLogger()) 43 err := eventBus.Start() 44 require.NoError(t, err) 45 t.Cleanup(func() { 46 if err := eventBus.Stop(); err != nil { 47 t.Error(err) 48 } 49 }) 50 51 assert.False(t, indexer.KVSinkEnabled([]indexer.EventSink{})) 52 assert.False(t, indexer.IndexingEnabled([]indexer.EventSink{})) 53 54 // event sink setup 55 pool, err := setupDB(t) 56 assert.Nil(t, err) 57 58 store := db.NewMemDB() 59 eventSinks := []indexer.EventSink{kv.NewEventSink(store), pSink} 60 assert.True(t, indexer.KVSinkEnabled(eventSinks)) 61 assert.True(t, indexer.IndexingEnabled(eventSinks)) 62 63 service := indexer.NewIndexerService(eventSinks, eventBus) 64 service.SetLogger(tmlog.TestingLogger()) 65 err = service.Start() 66 require.NoError(t, err) 67 t.Cleanup(func() { 68 if err := service.Stop(); err != nil { 69 t.Error(err) 70 } 71 }) 72 73 // publish block with txs 74 err = eventBus.PublishEventNewBlockHeader(types.EventDataNewBlockHeader{ 75 Header: types.Header{Height: 1}, 76 NumTxs: int64(2), 77 }) 78 require.NoError(t, err) 79 txResult1 := &abci.TxResult{ 80 Height: 1, 81 Index: uint32(0), 82 Tx: types.Tx("foo"), 83 Result: abci.ResponseDeliverTx{Code: 0}, 84 } 85 err = eventBus.PublishEventTx(types.EventDataTx{TxResult: *txResult1}) 86 require.NoError(t, err) 87 txResult2 := &abci.TxResult{ 88 Height: 1, 89 Index: uint32(1), 90 Tx: types.Tx("bar"), 91 Result: abci.ResponseDeliverTx{Code: 0}, 92 } 93 err = eventBus.PublishEventTx(types.EventDataTx{TxResult: *txResult2}) 94 require.NoError(t, err) 95 96 time.Sleep(100 * time.Millisecond) 97 98 res, err := eventSinks[0].GetTxByHash(types.Tx("foo").Hash()) 99 require.NoError(t, err) 100 require.Equal(t, txResult1, res) 101 102 ok, err := eventSinks[0].HasBlock(1) 103 require.NoError(t, err) 104 require.True(t, ok) 105 106 res, err = eventSinks[0].GetTxByHash(types.Tx("bar").Hash()) 107 require.NoError(t, err) 108 require.Equal(t, txResult2, res) 109 110 assert.Nil(t, teardown(t, pool)) 111 } 112 113 func readSchema() ([]*schema.Migration, error) { 114 filename := "./sink/psql/schema.sql" 115 contents, err := ioutil.ReadFile(filename) 116 if err != nil { 117 return nil, fmt.Errorf("failed to read sql file from '%s': %w", filename, err) 118 } 119 120 mg := &schema.Migration{} 121 mg.ID = time.Now().Local().String() + " db schema" 122 mg.Script = string(contents) 123 return append([]*schema.Migration{}, mg), nil 124 } 125 126 func resetDB(t *testing.T) { 127 q := "DROP TABLE IF EXISTS block_events,tx_events,tx_results" 128 _, err := psqldb.Exec(q) 129 assert.Nil(t, err) 130 131 q = "DROP TYPE IF EXISTS block_event_type" 132 _, err = psqldb.Exec(q) 133 assert.Nil(t, err) 134 } 135 136 func setupDB(t *testing.T) (*dockertest.Pool, error) { 137 t.Helper() 138 pool, err := dockertest.NewPool(os.Getenv("DOCKER_URL")) 139 assert.Nil(t, err) 140 141 resource, err = pool.RunWithOptions(&dockertest.RunOptions{ 142 Repository: psql.DriverName, 143 Tag: "13", 144 Env: []string{ 145 "POSTGRES_USER=" + user, 146 "POSTGRES_PASSWORD=" + password, 147 "POSTGRES_DB=" + dbName, 148 "listen_addresses = '*'", 149 }, 150 ExposedPorts: []string{port}, 151 }, func(config *docker.HostConfig) { 152 // set AutoRemove to true so that stopped container goes away by itself 153 config.AutoRemove = true 154 config.RestartPolicy = docker.RestartPolicy{ 155 Name: "no", 156 } 157 }) 158 159 assert.Nil(t, err) 160 161 // Set the container to expire in a minute to avoid orphaned containers 162 // hanging around 163 _ = resource.Expire(60) 164 165 conn := fmt.Sprintf(dsn, user, password, resource.GetPort(port+"/tcp"), dbName) 166 167 if err = pool.Retry(func() error { 168 var err error 169 170 pSink, psqldb, err = psql.NewEventSink(conn, "test-chainID") 171 172 if err != nil { 173 return err 174 } 175 176 return psqldb.Ping() 177 }); err != nil { 178 assert.Error(t, err) 179 } 180 181 resetDB(t) 182 183 sm, err := readSchema() 184 assert.Nil(t, err) 185 186 err = schema.NewMigrator().Apply(psqldb, sm) 187 assert.Nil(t, err) 188 189 return pool, nil 190 } 191 192 func teardown(t *testing.T, pool *dockertest.Pool) error { 193 t.Helper() 194 // When you're done, kill and remove the container 195 assert.Nil(t, pool.Purge(resource)) 196 return psqldb.Close() 197 }