github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/integration/rpcquery/query_server_test.go (about)

     1  // +build integration
     2  
     3  package rpcquery
     4  
     5  import (
     6  	"context"
     7  	"fmt"
     8  	"io"
     9  	"testing"
    10  
    11  	"github.com/hyperledger/burrow/integration"
    12  
    13  	"github.com/tendermint/tendermint/crypto/tmhash"
    14  
    15  	"github.com/hyperledger/burrow/acm"
    16  	"github.com/hyperledger/burrow/event/query"
    17  	"github.com/hyperledger/burrow/execution/names"
    18  	"github.com/hyperledger/burrow/genesis"
    19  	"github.com/hyperledger/burrow/integration/rpctest"
    20  	"github.com/hyperledger/burrow/rpc/rpcquery"
    21  	"github.com/stretchr/testify/assert"
    22  	"github.com/stretchr/testify/require"
    23  )
    24  
    25  func TestQueryServer(t *testing.T) {
    26  	kern, shutdown := integration.RunNode(t, rpctest.GenesisDoc, rpctest.PrivateAccounts)
    27  	defer shutdown()
    28  
    29  	t.Run("Status", func(t *testing.T) {
    30  		cli := rpctest.NewQueryClient(t, kern.GRPCListenAddress().String())
    31  		status, err := cli.Status(context.Background(), &rpcquery.StatusParam{})
    32  		require.NoError(t, err)
    33  		assert.Equal(t, rpctest.PrivateAccounts[0].GetPublicKey(), status.ValidatorInfo.PublicKey)
    34  		assert.Equal(t, rpctest.GenesisDoc.GetChainID(), status.ChainID)
    35  		for i := 0; i < 3; i++ {
    36  			// Unless we get lucky this is an error
    37  			_, err = cli.Status(context.Background(), &rpcquery.StatusParam{
    38  				BlockTimeWithin: "1ns",
    39  			})
    40  			if err != nil {
    41  				break
    42  			}
    43  		}
    44  		require.Error(t, err)
    45  		assert.Contains(t, err.Error(), "have not committed block with sufficiently recent timestamp")
    46  
    47  		for i := 0; i < 3; i++ {
    48  			// Unless we get lucky this is an error
    49  			_, err = cli.Status(context.Background(), &rpcquery.StatusParam{
    50  				BlockSeenTimeWithin: "1ns",
    51  			})
    52  			if err != nil {
    53  				break
    54  			}
    55  		}
    56  		require.Error(t, err)
    57  		assert.Contains(t, err.Error(), "have not committed a block sufficiently recently")
    58  	})
    59  
    60  	t.Run("GetAccount", func(t *testing.T) {
    61  		cli := rpctest.NewQueryClient(t, kern.GRPCListenAddress().String())
    62  		acc, err := cli.GetAccount(context.Background(), &rpcquery.GetAccountParam{
    63  			Address: rpctest.PrivateAccounts[2].GetAddress(),
    64  		})
    65  		require.NoError(t, err)
    66  		genAcc := rpctest.GenesisDoc.Accounts[2]
    67  		genAccOut := genesis.GenesisAccountFromAccount(rpctest.GenesisDoc.Accounts[2].Name, acc)
    68  		// Normalise
    69  		genAcc.Permissions.Roles = nil
    70  		genAccOut.Permissions.Roles = nil
    71  		assert.Equal(t, genAcc, genAccOut)
    72  	})
    73  
    74  	t.Run("ListAccounts", func(t *testing.T) {
    75  		cli := rpctest.NewQueryClient(t, kern.GRPCListenAddress().String())
    76  		stream, err := cli.ListAccounts(context.Background(), &rpcquery.ListAccountsParam{})
    77  		require.NoError(t, err)
    78  		var accs []*acm.Account
    79  		acc, err := stream.Recv()
    80  		for err == nil {
    81  			accs = append(accs, acc)
    82  			acc, err = stream.Recv()
    83  		}
    84  		if err != nil && err != io.EOF {
    85  			t.Fatalf("unexpected error: %v", err)
    86  		}
    87  		assert.Len(t, accs, len(rpctest.GenesisDoc.Accounts)+1)
    88  	})
    89  
    90  	t.Run("ListNames", func(t *testing.T) {
    91  		tcli := rpctest.NewTransactClient(t, kern.GRPCListenAddress().String())
    92  		dataA, dataB := "NO TAMBOURINES", "ELEPHANTS WELCOME"
    93  		n := 8
    94  		for i := 0; i < n; i++ {
    95  			name := fmt.Sprintf("Flub/%v", i)
    96  			if i%2 == 0 {
    97  				_, err := rpctest.UpdateName(tcli, rpctest.PrivateAccounts[0].GetAddress(), name, dataA, 200)
    98  				require.NoError(t, err)
    99  			} else {
   100  				_, err := rpctest.UpdateName(tcli, rpctest.PrivateAccounts[1].GetAddress(), name, dataB, 200)
   101  				require.NoError(t, err)
   102  			}
   103  		}
   104  		qcli := rpctest.NewQueryClient(t, kern.GRPCListenAddress().String())
   105  		entries := receiveNames(t, qcli, "")
   106  		assert.Len(t, entries, n)
   107  		entries = receiveNames(t, qcli, query.NewBuilder().AndEquals("Data", dataA).String())
   108  		if assert.Len(t, entries, n/2) {
   109  			assert.Equal(t, dataA, entries[0].Data)
   110  		}
   111  	})
   112  
   113  	t.Run("GetBlockHeader", func(t *testing.T) {
   114  		qcli := rpctest.NewQueryClient(t, kern.GRPCListenAddress().String())
   115  		ecli := rpctest.NewExecutionEventsClient(t, kern.GRPCListenAddress().String())
   116  		height := 1
   117  		err := rpctest.WaitNBlocks(ecli, 1)
   118  		require.NoError(t, err)
   119  		header, err := qcli.GetBlockHeader(context.Background(), &rpcquery.GetBlockParam{Height: uint64(height)})
   120  		require.NoError(t, err)
   121  		assert.Equal(t, kern.Blockchain.ChainID(), header.ChainID)
   122  		assert.Equal(t, int64(height), header.Height)
   123  		assert.Len(t, header.AppHash, tmhash.Size)
   124  	})
   125  }
   126  
   127  func receiveNames(t testing.TB, qcli rpcquery.QueryClient, query string) []*names.Entry {
   128  	stream, err := qcli.ListNames(context.Background(), &rpcquery.ListNamesParam{
   129  		Query: query,
   130  	})
   131  	require.NoError(t, err)
   132  	var entries []*names.Entry
   133  	entry, err := stream.Recv()
   134  	for err == nil {
   135  		entries = append(entries, entry)
   136  		entry, err = stream.Recv()
   137  	}
   138  	if err != io.EOF {
   139  		t.Fatalf("unexpected error: %v", err)
   140  	}
   141  	return entries
   142  }