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 }