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