github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/vent/service/consumer_postgres_test.go (about) 1 // +build integration,!ethereum 2 3 package service_test 4 5 import ( 6 "encoding/json" 7 "testing" 8 "time" 9 10 "github.com/hyperledger/burrow/integration" 11 "github.com/hyperledger/burrow/integration/rpctest" 12 13 "github.com/stretchr/testify/assert" 14 15 "github.com/hyperledger/burrow/vent/types" 16 "github.com/lib/pq" 17 "github.com/stretchr/testify/require" 18 19 "github.com/hyperledger/burrow/vent/test" 20 ) 21 22 func TestPostgresConsumer(t *testing.T) { 23 privateAccounts := rpctest.PrivateAccounts 24 kern, shutdown := integration.RunNode(t, rpctest.GenesisDoc, privateAccounts) 25 defer shutdown() 26 inputAddress := privateAccounts[0].GetAddress() 27 grpcAddress := kern.GRPCListenAddress().String() 28 tcli := test.NewBurrowTransactClient(t, grpcAddress) 29 30 t.Parallel() 31 time.Sleep(2 * time.Second) 32 33 t.Run("Group", func(t *testing.T) { 34 t.Run("PostgresConsumer", func(t *testing.T) { 35 testConsumer(t, kern.Blockchain.ChainID(), test.PostgresVentConfig(grpcAddress), tcli, inputAddress) 36 }) 37 38 t.Run("PostgresInvalidUTF8", func(t *testing.T) { 39 testInvalidUTF8(t, test.PostgresVentConfig(grpcAddress), tcli, inputAddress) 40 }) 41 42 t.Run("PostgresDeleteEvent", func(t *testing.T) { 43 testDeleteEvent(t, kern.Blockchain.ChainID(), test.PostgresVentConfig(grpcAddress), tcli, inputAddress) 44 }) 45 46 t.Run("PostgresResume", func(t *testing.T) { 47 testResume(t, test.PostgresVentConfig(grpcAddress)) 48 }) 49 50 t.Run("PostgresTriggers", func(t *testing.T) { 51 tCli := test.NewBurrowTransactClient(t, kern.GRPCListenAddress().String()) 52 create := test.CreateContract(t, tCli, inputAddress) 53 54 // generate events 55 name := "TestTriggerEvent" 56 description := "Trigger it!" 57 txe := test.CallAddEvent(t, tCli, inputAddress, create.Receipt.ContractAddress, name, description) 58 59 cfg := test.PostgresVentConfig(grpcAddress) 60 // create test db 61 _, closeDB := test.NewTestDB(t, cfg) 62 defer closeDB() 63 64 // Create a postgres notification listener 65 listener := pq.NewListener(cfg.DBURL, time.Second, time.Second*20, func(event pq.ListenerEventType, err error) { 66 require.NoError(t, err) 67 }) 68 69 // These are defined in sqlsol_view.json 70 err := listener.Listen("meta") 71 require.NoError(t, err) 72 73 err = listener.Listen("keyed_meta") 74 require.NoError(t, err) 75 76 err = listener.Listen(types.BlockHeightLabel) 77 require.NoError(t, err) 78 79 type payload struct { 80 Height uint64 `json:"_height"` 81 } 82 83 heightCh := make(chan uint64) 84 notifications := make(map[string]string) 85 go func() { 86 for n := range listener.Notify { 87 notifications[n.Channel] = n.Extra 88 if n.Channel == types.BlockHeightLabel { 89 pl := new(payload) 90 err := json.Unmarshal([]byte(n.Extra), pl) 91 if err != nil { 92 panic(err) 93 } 94 if pl.Height >= txe.Height { 95 heightCh <- pl.Height 96 return 97 } 98 } 99 } 100 }() 101 resolveSpec(cfg, testViewSpec) 102 runConsumer(t, cfg) 103 104 // Give events a chance 105 const timeout = 3 * time.Second 106 select { 107 case <-time.After(timeout): 108 t.Fatalf("timed out after %v waiting for notification", timeout) 109 case height := <-heightCh: 110 // Assert we get expected returns 111 t.Logf("latest height: %d, txe height: %d", height, txe.Height) 112 assert.True(t, height >= txe.Height) 113 } 114 assert.Equal(t, `{"_action" : "INSERT", "testdescription" : "5472696767657220697421000000000000000000000000000000000000000000", "testname" : "TestTriggerEvent"}`, 115 notifications["meta"]) 116 assert.Equal(t, `{"_action" : "INSERT", "testdescription" : "5472696767657220697421000000000000000000000000000000000000000000", "testkey" : "\\x544553545f4556454e5453000000000000000000000000000000000000000000", "testname" : "TestTriggerEvent"}`, 117 notifications["keyed_meta"]) 118 }) 119 }) 120 }