github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/vent/sqldb/sqldb_postgres_test.go (about)

     1  // +build integration
     2  
     3  package sqldb_test
     4  
     5  import (
     6  	"encoding/json"
     7  	"fmt"
     8  	"strconv"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/hyperledger/burrow/vent/sqldb/adapters"
    13  	"github.com/hyperledger/burrow/vent/test"
    14  	"github.com/hyperledger/burrow/vent/types"
    15  	"github.com/lib/pq"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  var tables = types.DefaultSQLTableNames
    20  var columns = types.DefaultSQLColumnNames
    21  
    22  func TestPostgresSynchronizeDB(t *testing.T) {
    23  	testSynchronizeDB(t, test.PostgresVentConfig(""))
    24  }
    25  
    26  func TestPostgresCleanDB(t *testing.T) {
    27  	testCleanDB(t, test.PostgresVentConfig(""))
    28  }
    29  
    30  func TestPostgresSetBlock(t *testing.T) {
    31  	testSetBlock(t, test.PostgresVentConfig(""))
    32  }
    33  
    34  func TestRestore(t *testing.T) {
    35  	testRestore(t, test.PostgresVentConfig(""))
    36  }
    37  
    38  func TestPostgresBlockNotification(t *testing.T) {
    39  	cfg := test.PostgresVentConfig("")
    40  	db, closeDB := test.NewTestDB(t, cfg)
    41  	defer closeDB()
    42  
    43  	errp := db.Ping()
    44  	require.NoError(t, errp)
    45  
    46  	functionName := "notify_height"
    47  	channelName := "height_notification"
    48  	pad := db.DBAdapter.(*adapters.PostgresAdapter)
    49  
    50  	// Run twice to show idempotency
    51  	for i := 0; i < 2; i++ {
    52  		query := pad.CreateNotifyFunctionQuery(functionName, channelName, columns.Height)
    53  		_, err := db.DB.Exec(query)
    54  		require.NoError(t, err)
    55  
    56  		query = pad.CreateTriggerQuery("notify_height_trigger", tables.Log, functionName)
    57  		_, err = db.DB.Exec(query)
    58  		require.NoError(t, err)
    59  	}
    60  
    61  	listener := pq.NewListener(cfg.DBURL, time.Second, time.Second*20, func(event pq.ListenerEventType, err error) {
    62  		require.NoError(t, err)
    63  	})
    64  	err := listener.Listen(channelName)
    65  	require.NoError(t, err)
    66  
    67  	// new block
    68  	str, dat := getBlock()
    69  
    70  	errCh := make(chan error)
    71  	go func() {
    72  		type payload struct {
    73  			Height string `json:"_height"`
    74  		}
    75  		for n := range listener.NotificationChannel() {
    76  			pl := new(payload)
    77  			err := json.Unmarshal([]byte(n.Extra), pl)
    78  			if err != nil {
    79  				errCh <- err
    80  				return
    81  			}
    82  			if pl.Height != "" {
    83  				if strconv.FormatUint(dat.BlockHeight, 10) != pl.Height {
    84  					errCh <- fmt.Errorf("got height %s from notification but expected %d",
    85  						pl.Height, dat.BlockHeight)
    86  				}
    87  				errCh <- nil
    88  				return
    89  			}
    90  		}
    91  	}()
    92  
    93  	// Set it
    94  	err = db.SetBlock(test.ChainID, str, dat)
    95  	require.NoError(t, err)
    96  
    97  	// read
    98  	_, err = db.LastBlockHeight(test.ChainID)
    99  	require.NoError(t, err)
   100  
   101  	_, err = db.GetBlock(test.ChainID, dat.BlockHeight)
   102  	require.NoError(t, err)
   103  
   104  	const timeout = 2 * time.Second
   105  	select {
   106  	case <-time.After(timeout):
   107  		t.Fatalf("timed out waiting for notification after %s", timeout)
   108  	case err = <-errCh:
   109  		require.NoError(t, err)
   110  	}
   111  }