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 }