github.com/Finschia/finschia-sdk@v0.49.1/client/grpc/ocservice/service_test.go (about)

     1  package ocservice_test
     2  
     3  import (
     4  	"context"
     5  	"encoding/base64"
     6  	"fmt"
     7  	"testing"
     8  
     9  	"github.com/Finschia/ostracon/libs/bytes"
    10  	"github.com/stretchr/testify/suite"
    11  
    12  	"github.com/Finschia/finschia-sdk/client/grpc/ocservice"
    13  	codectypes "github.com/Finschia/finschia-sdk/codec/types"
    14  	cryptotypes "github.com/Finschia/finschia-sdk/crypto/types"
    15  	"github.com/Finschia/finschia-sdk/testutil/network"
    16  	"github.com/Finschia/finschia-sdk/testutil/rest"
    17  	qtypes "github.com/Finschia/finschia-sdk/types/query"
    18  	"github.com/Finschia/finschia-sdk/version"
    19  )
    20  
    21  type IntegrationTestSuite struct {
    22  	suite.Suite
    23  
    24  	cfg     network.Config
    25  	network *network.Network
    26  
    27  	queryClient ocservice.ServiceClient
    28  }
    29  
    30  func (s *IntegrationTestSuite) SetupSuite() {
    31  	s.T().Log("setting up integration test suite")
    32  
    33  	cfg := network.DefaultConfig()
    34  	cfg.NumValidators = 1
    35  
    36  	s.cfg = cfg
    37  	s.network = network.New(s.T(), cfg)
    38  
    39  	s.Require().NotNil(s.network)
    40  
    41  	_, err := s.network.WaitForHeight(1)
    42  	s.Require().NoError(err)
    43  
    44  	s.queryClient = ocservice.NewServiceClient(s.network.Validators[0].ClientCtx)
    45  }
    46  
    47  func (s *IntegrationTestSuite) TearDownSuite() {
    48  	s.T().Log("tearing down integration test suite")
    49  	s.network.Cleanup()
    50  }
    51  
    52  func (s *IntegrationTestSuite) TestQueryNodeInfo() {
    53  	val := s.network.Validators[0]
    54  
    55  	res, err := s.queryClient.GetNodeInfo(context.Background(), &ocservice.GetNodeInfoRequest{})
    56  	s.Require().NoError(err)
    57  	s.Require().Equal(res.ApplicationVersion.AppName, version.NewInfo().AppName)
    58  
    59  	restRes, err := rest.GetRequest(fmt.Sprintf("%s/lbm/base/ostracon/v1/node_info", val.APIAddress))
    60  	s.Require().NoError(err)
    61  	var getInfoRes ocservice.GetNodeInfoResponse
    62  	s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(restRes, &getInfoRes))
    63  	s.Require().Equal(getInfoRes.ApplicationVersion.AppName, version.NewInfo().AppName)
    64  }
    65  
    66  func (s *IntegrationTestSuite) TestQuerySyncing() {
    67  	val := s.network.Validators[0]
    68  
    69  	_, err := s.queryClient.GetSyncing(context.Background(), &ocservice.GetSyncingRequest{})
    70  	s.Require().NoError(err)
    71  
    72  	restRes, err := rest.GetRequest(fmt.Sprintf("%s/lbm/base/ostracon/v1/syncing", val.APIAddress))
    73  	s.Require().NoError(err)
    74  	var syncingRes ocservice.GetSyncingResponse
    75  	s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(restRes, &syncingRes))
    76  }
    77  
    78  func (s *IntegrationTestSuite) TestQueryLatestBlock() {
    79  	val := s.network.Validators[0]
    80  	_, err := s.queryClient.GetLatestBlock(context.Background(), &ocservice.GetLatestBlockRequest{})
    81  	s.Require().NoError(err)
    82  
    83  	restRes, err := rest.GetRequest(fmt.Sprintf("%s/lbm/base/ostracon/v1/blocks/latest", val.APIAddress))
    84  	s.Require().NoError(err)
    85  	var blockInfoRes ocservice.GetLatestBlockResponse
    86  	s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(restRes, &blockInfoRes))
    87  }
    88  
    89  func (s *IntegrationTestSuite) TestQueryBlockByHash() {
    90  	val := s.network.Validators[0]
    91  	node, _ := val.ClientCtx.GetNode()
    92  	blk, _ := node.Block(context.Background(), nil)
    93  	blkhash := blk.BlockID.Hash
    94  
    95  	tcs := []struct {
    96  		hash  bytes.HexBytes
    97  		isErr bool
    98  		err   string
    99  	}{
   100  		{blkhash, false, ""},
   101  		{bytes.HexBytes("wrong hash"), true, "the length of block hash must be 32: invalid request"},
   102  		{bytes.HexBytes(""), true, "block hash cannot be empty"},
   103  	}
   104  
   105  	for _, tc := range tcs {
   106  		_, err := s.queryClient.GetBlockByHash(context.Background(), &ocservice.GetBlockByHashRequest{Hash: tc.hash})
   107  		if tc.isErr {
   108  			s.Require().Error(err)
   109  			s.Require().Contains(err.Error(), tc.err)
   110  		} else {
   111  			s.Require().NoError(err)
   112  		}
   113  	}
   114  
   115  	restRes, err := rest.GetRequest(fmt.Sprintf("%s/lbm/base/ostracon/v1/block/%s", val.APIAddress, base64.URLEncoding.EncodeToString(blkhash)))
   116  	s.Require().NoError(err)
   117  	var blockInfoRes ocservice.GetBlockByHashResponse
   118  	s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(restRes, &blockInfoRes))
   119  	blockId := blockInfoRes.GetBlockId()
   120  	s.Require().Equal(blkhash, bytes.HexBytes(blockId.Hash))
   121  
   122  	block := blockInfoRes.GetBlock()
   123  	s.Require().Equal(val.ClientCtx.ChainID, block.Header.ChainID)
   124  }
   125  
   126  func (s *IntegrationTestSuite) TestGetLatestBlock() {
   127  	val := s.network.Validators[0]
   128  	latestHeight, err := s.network.LatestHeight()
   129  	s.Require().NoError(err)
   130  
   131  	blockRes, err := s.queryClient.GetLatestBlock(context.Background(), &ocservice.GetLatestBlockRequest{})
   132  	s.Require().NoError(err)
   133  	s.Require().NotNil(blockRes)
   134  	s.Require().Equal(latestHeight, blockRes.Block.Header.Height)
   135  
   136  	restRes, err := rest.GetRequest(fmt.Sprintf("%s/lbm/base/ostracon/v1/blocks/latest", val.APIAddress))
   137  	s.Require().NoError(err)
   138  	var blockInfoRes ocservice.GetLatestBlockResponse
   139  	s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(restRes, &blockInfoRes))
   140  	s.Require().Equal(blockRes.Block.Header.Height, blockInfoRes.Block.Header.Height)
   141  }
   142  
   143  func (s *IntegrationTestSuite) TestQueryBlockByHeight() {
   144  	val := s.network.Validators[0]
   145  	_, err := s.queryClient.GetBlockByHeight(context.Background(), &ocservice.GetBlockByHeightRequest{})
   146  	s.Require().Error(err)
   147  
   148  	_, err = s.queryClient.GetBlockByHeight(context.Background(), &ocservice.GetBlockByHeightRequest{Height: 1})
   149  	s.Require().NoError(err)
   150  
   151  	restRes, err := rest.GetRequest(fmt.Sprintf("%s/lbm/base/ostracon/v1/blocks/%d", val.APIAddress, 1))
   152  	s.Require().NoError(err)
   153  	var blockInfoRes ocservice.GetBlockByHeightResponse
   154  	s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(restRes, &blockInfoRes))
   155  
   156  	block := blockInfoRes.GetBlock()
   157  	s.Require().Equal(int64(1), block.Header.Height)
   158  }
   159  
   160  func (s *IntegrationTestSuite) TestQueryBlockResultsByHeight() {
   161  	val := s.network.Validators[0]
   162  	_, err := s.queryClient.GetBlockResultsByHeight(context.Background(), &ocservice.GetBlockResultsByHeightRequest{Height: 1})
   163  	s.Require().NoError(err)
   164  
   165  	restRes, err := rest.GetRequest(fmt.Sprintf("%s/lbm/base/ostracon/v1/blockresults/%d", val.APIAddress, 1))
   166  	s.Require().NoError(err)
   167  	var blockResultsRes ocservice.GetBlockResultsByHeightResponse
   168  	s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(restRes, &blockResultsRes))
   169  
   170  	txResult := blockResultsRes.GetTxsResults()
   171  	s.Require().Equal(0, len(txResult))
   172  
   173  	beginBlock := blockResultsRes.GetResBeginBlock()
   174  	s.Require().Equal(6, len(beginBlock.Events)) // coinbase event (2) + transfer mintModule to feeCollectorName(3) + mint event
   175  
   176  	endBlock := blockResultsRes.GetResEndBlock()
   177  	s.Require().Equal(0, len(endBlock.Events))
   178  }
   179  
   180  func (s *IntegrationTestSuite) TestQueryLatestValidatorSet() {
   181  	val := s.network.Validators[0]
   182  
   183  	// nil pagination
   184  	res, err := s.queryClient.GetLatestValidatorSet(context.Background(), &ocservice.GetLatestValidatorSetRequest{
   185  		Pagination: nil,
   186  	})
   187  	s.Require().NoError(err)
   188  	s.Require().Equal(1, len(res.Validators))
   189  	content, ok := res.Validators[0].PubKey.GetCachedValue().(cryptotypes.PubKey)
   190  	s.Require().Equal(true, ok)
   191  	s.Require().Equal(content, val.PubKey)
   192  
   193  	// with pagination
   194  	_, err = s.queryClient.GetLatestValidatorSet(context.Background(), &ocservice.GetLatestValidatorSetRequest{Pagination: &qtypes.PageRequest{
   195  		Offset: 0,
   196  		Limit:  10,
   197  	}})
   198  	s.Require().NoError(err)
   199  
   200  	// rest request without pagination
   201  	_, err = rest.GetRequest(fmt.Sprintf("%s/lbm/base/ostracon/v1/validatorsets/latest", val.APIAddress))
   202  	s.Require().NoError(err)
   203  
   204  	// rest request with pagination
   205  	restRes, err := rest.GetRequest(fmt.Sprintf("%s/lbm/base/ostracon/v1/validatorsets/latest?pagination.offset=%d&pagination.limit=%d", val.APIAddress, 0, 1))
   206  	s.Require().NoError(err)
   207  	var validatorSetRes ocservice.GetLatestValidatorSetResponse
   208  	s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(restRes, &validatorSetRes))
   209  	s.Require().Equal(1, len(validatorSetRes.Validators))
   210  	anyPub, err := codectypes.NewAnyWithValue(val.PubKey)
   211  	s.Require().NoError(err)
   212  	s.Require().Equal(validatorSetRes.Validators[0].PubKey, anyPub)
   213  }
   214  
   215  func (s *IntegrationTestSuite) TestLatestValidatorSet_GRPC() {
   216  	vals := s.network.Validators
   217  	testCases := []struct {
   218  		name      string
   219  		req       *ocservice.GetLatestValidatorSetRequest
   220  		expErr    bool
   221  		expErrMsg string
   222  	}{
   223  		{"nil request", nil, true, "cannot be nil"},
   224  		{"no pagination", &ocservice.GetLatestValidatorSetRequest{}, false, ""},
   225  		{"with pagination", &ocservice.GetLatestValidatorSetRequest{Pagination: &qtypes.PageRequest{Offset: 0, Limit: uint64(len(vals))}}, false, ""},
   226  	}
   227  	for _, tc := range testCases {
   228  		s.Run(tc.name, func() {
   229  			grpcRes, err := s.queryClient.GetLatestValidatorSet(context.Background(), tc.req)
   230  			if tc.expErr {
   231  				s.Require().Error(err)
   232  				s.Require().Contains(err.Error(), tc.expErrMsg)
   233  			} else {
   234  				s.Require().NoError(err)
   235  				s.Require().Len(grpcRes.Validators, len(vals))
   236  				s.Require().Equal(grpcRes.Pagination.Total, uint64(len(vals)))
   237  				content, ok := grpcRes.Validators[0].PubKey.GetCachedValue().(cryptotypes.PubKey)
   238  				s.Require().Equal(true, ok)
   239  				s.Require().Equal(content, vals[0].PubKey)
   240  			}
   241  		})
   242  	}
   243  }
   244  
   245  func (s *IntegrationTestSuite) TestLatestValidatorSet_GRPCGateway() {
   246  	vals := s.network.Validators
   247  	testCases := []struct {
   248  		name      string
   249  		url       string
   250  		expErr    bool
   251  		expErrMsg string
   252  	}{
   253  		{"no pagination", fmt.Sprintf("%s/lbm/base/ostracon/v1/validatorsets/latest", vals[0].APIAddress), false, ""},
   254  		{"pagination invalid fields", fmt.Sprintf("%s/lbm/base/ostracon/v1/validatorsets/latest?pagination.offset=-1&pagination.limit=-2", vals[0].APIAddress), true, "strconv.ParseUint"},
   255  		{"with pagination", fmt.Sprintf("%s/lbm/base/ostracon/v1/validatorsets/latest?pagination.offset=0&pagination.limit=2", vals[0].APIAddress), false, ""},
   256  	}
   257  	for _, tc := range testCases {
   258  		s.Run(tc.name, func() {
   259  			res, err := rest.GetRequest(tc.url)
   260  			s.Require().NoError(err)
   261  			if tc.expErr {
   262  				s.Require().Contains(string(res), tc.expErrMsg)
   263  			} else {
   264  				var result ocservice.GetLatestValidatorSetResponse
   265  				err = vals[0].ClientCtx.Codec.UnmarshalJSON(res, &result)
   266  				s.Require().NoError(err)
   267  				s.Require().Equal(uint64(len(vals)), result.Pagination.Total)
   268  				anyPub, err := codectypes.NewAnyWithValue(vals[0].PubKey)
   269  				s.Require().NoError(err)
   270  				s.Require().Equal(result.Validators[0].PubKey, anyPub)
   271  			}
   272  		})
   273  	}
   274  }
   275  
   276  func (s *IntegrationTestSuite) TestValidatorSetByHeight_GRPC() {
   277  	vals := s.network.Validators
   278  	testCases := []struct {
   279  		name      string
   280  		req       *ocservice.GetValidatorSetByHeightRequest
   281  		expErr    bool
   282  		expErrMsg string
   283  	}{
   284  		{"nil request", nil, true, "request cannot be nil"},
   285  		{"empty request", &ocservice.GetValidatorSetByHeightRequest{}, true, "height must be greater than 0"},
   286  		{"no pagination", &ocservice.GetValidatorSetByHeightRequest{Height: 1}, false, ""},
   287  		{"with pagination", &ocservice.GetValidatorSetByHeightRequest{Height: 1, Pagination: &qtypes.PageRequest{Offset: 0, Limit: 1}}, false, ""},
   288  	}
   289  	for _, tc := range testCases {
   290  		s.Run(tc.name, func() {
   291  			grpcRes, err := s.queryClient.GetValidatorSetByHeight(context.Background(), tc.req)
   292  			if tc.expErr {
   293  				s.Require().Error(err)
   294  				s.Require().Contains(err.Error(), tc.expErrMsg)
   295  			} else {
   296  				s.Require().NoError(err)
   297  				s.Require().Len(grpcRes.Validators, len(vals))
   298  				s.Require().Equal(grpcRes.Pagination.Total, uint64(len(vals)))
   299  			}
   300  		})
   301  	}
   302  }
   303  
   304  func (s *IntegrationTestSuite) TestValidatorSetByHeight_GRPCGateway() {
   305  	vals := s.network.Validators
   306  	testCases := []struct {
   307  		name      string
   308  		url       string
   309  		expErr    bool
   310  		expErrMsg string
   311  	}{
   312  		{"invalid height", fmt.Sprintf("%s/lbm/base/ostracon/v1/validatorsets/%d", vals[0].APIAddress, -1), true, "height must be greater than 0"},
   313  		{"no pagination", fmt.Sprintf("%s/lbm/base/ostracon/v1/validatorsets/%d", vals[0].APIAddress, 1), false, ""},
   314  		{"pagination invalid fields", fmt.Sprintf("%s/lbm/base/ostracon/v1/validatorsets/%d?pagination.offset=-1&pagination.limit=-2", vals[0].APIAddress, 1), true, "strconv.ParseUint"},
   315  		{"with pagination", fmt.Sprintf("%s/lbm/base/ostracon/v1/validatorsets/%d?pagination.offset=0&pagination.limit=2", vals[0].APIAddress, 1), false, ""},
   316  	}
   317  	for _, tc := range testCases {
   318  		s.Run(tc.name, func() {
   319  			res, err := rest.GetRequest(tc.url)
   320  			s.Require().NoError(err)
   321  			if tc.expErr {
   322  				s.Require().Contains(string(res), tc.expErrMsg)
   323  			} else {
   324  				var result ocservice.GetValidatorSetByHeightResponse
   325  				err = vals[0].ClientCtx.Codec.UnmarshalJSON(res, &result)
   326  				s.Require().NoError(err)
   327  				s.Require().Equal(uint64(len(vals)), result.Pagination.Total)
   328  			}
   329  		})
   330  	}
   331  }
   332  
   333  func TestIntegrationTestSuite(t *testing.T) {
   334  	suite.Run(t, new(IntegrationTestSuite))
   335  }