package rest_test import ( "fmt" "testing" "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/suite" "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" grpctypes "github.com/cosmos/cosmos-sdk/types/grpc" "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/cosmos-sdk/types/rest" "github.com/cosmos/cosmos-sdk/x/distribution/types" ) type IntegrationTestSuite struct { suite.Suite cfg network.Config network *network.Network } func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") cfg := network.DefaultConfig() cfg.NumValidators = 1 s.cfg = cfg s.network = network.New(s.T(), cfg) _, err := s.network.WaitForHeight(1) s.Require().NoError(err) } func (s *IntegrationTestSuite) TestQueryParamsGRPC() { val := s.network.Validators[0] baseURL := val.APIAddress testCases := []struct { name string url string respType proto.Message expected proto.Message }{ { "gRPC request params", fmt.Sprintf("%s/cosmos/distribution/v1beta1/params", baseURL), &types.QueryParamsResponse{}, &types.QueryParamsResponse{ Params: types.DefaultParams(), }, }, } for _, tc := range testCases { tc := tc resp, err := rest.GetRequest(tc.url) s.Run(tc.name, func() { s.Require().NoError(err) s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType)) s.Require().Equal(tc.expected, tc.respType) }) } } func (s *IntegrationTestSuite) TestQueryOutstandingRewardsGRPC() { val := s.network.Validators[0] baseURL := val.APIAddress rewards, err := sdk.ParseDecCoins("19.6stake") s.Require().NoError(err) testCases := []struct { name string url string headers map[string]string expErr bool respType proto.Message expected proto.Message }{ { "gRPC request params with wrong validator address", fmt.Sprintf("%s/cosmos/distribution/v1beta1/validators/%s/outstanding_rewards", baseURL, "wrongAddress"), map[string]string{}, true, &types.QueryValidatorOutstandingRewardsResponse{}, &types.QueryValidatorOutstandingRewardsResponse{}, }, { "gRPC request params valid address", fmt.Sprintf("%s/cosmos/distribution/v1beta1/validators/%s/outstanding_rewards", baseURL, val.ValAddress.String()), map[string]string{ grpctypes.GRPCBlockHeightHeader: "2", }, false, &types.QueryValidatorOutstandingRewardsResponse{}, &types.QueryValidatorOutstandingRewardsResponse{ Rewards: types.ValidatorOutstandingRewards{ Rewards: rewards, }, }, }, } for _, tc := range testCases { tc := tc resp, err := testutil.GetRequestWithHeaders(tc.url, tc.headers) s.Run(tc.name, func() { if tc.expErr { s.Require().Error(val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType)) } else { s.Require().NoError(err) s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType)) s.Require().Equal(tc.expected.String(), tc.respType.String()) } }) } } func (s *IntegrationTestSuite) TestQueryValidatorCommissionGRPC() { val := s.network.Validators[0] baseURL := val.APIAddress commission, err := sdk.ParseDecCoins("9.8stake") s.Require().NoError(err) testCases := []struct { name string url string headers map[string]string expErr bool respType proto.Message expected proto.Message }{ { "gRPC request params with wrong validator address", fmt.Sprintf("%s/cosmos/distribution/v1beta1/validators/%s/commission", baseURL, "wrongAddress"), map[string]string{}, true, &types.QueryValidatorCommissionResponse{}, &types.QueryValidatorCommissionResponse{}, }, { "gRPC request params valid address", fmt.Sprintf("%s/cosmos/distribution/v1beta1/validators/%s/commission", baseURL, val.ValAddress.String()), map[string]string{ grpctypes.GRPCBlockHeightHeader: "2", }, false, &types.QueryValidatorCommissionResponse{}, &types.QueryValidatorCommissionResponse{ Commission: types.ValidatorAccumulatedCommission{ Commission: commission, }, }, }, } for _, tc := range testCases { tc := tc resp, err := testutil.GetRequestWithHeaders(tc.url, tc.headers) s.Run(tc.name, func() { if tc.expErr { s.Require().Error(val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType)) } else { s.Require().NoError(err) s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType)) s.Require().Equal(tc.expected.String(), tc.respType.String()) } }) } } func (s *IntegrationTestSuite) TestQuerySlashesGRPC() { val := s.network.Validators[0] baseURL := val.APIAddress testCases := []struct { name string url string expErr bool respType proto.Message expected proto.Message }{ { "invalid validator address", fmt.Sprintf("%s/cosmos/distribution/v1beta1/validators/%s/slashes", baseURL, ""), true, &types.QueryValidatorSlashesResponse{}, nil, }, { "invalid start height", fmt.Sprintf("%s/cosmos/distribution/v1beta1/validators/%s/slashes?starting_height=%s&ending_height=%s", baseURL, val.ValAddress.String(), "-1", "3"), true, &types.QueryValidatorSlashesResponse{}, nil, }, { "invalid start height", fmt.Sprintf("%s/cosmos/distribution/v1beta1/validators/%s/slashes?starting_height=%s&ending_height=%s", baseURL, val.ValAddress.String(), "1", "-3"), true, &types.QueryValidatorSlashesResponse{}, nil, }, { "valid request get slashes", fmt.Sprintf("%s/cosmos/distribution/v1beta1/validators/%s/slashes?starting_height=%s&ending_height=%s", baseURL, val.ValAddress.String(), "1", "3"), false, &types.QueryValidatorSlashesResponse{}, &types.QueryValidatorSlashesResponse{ Pagination: &query.PageResponse{}, }, }, } for _, tc := range testCases { tc := tc resp, err := rest.GetRequest(tc.url) s.Run(tc.name, func() { if tc.expErr { s.Require().Error(val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType)) } else { s.Require().NoError(err) s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType)) s.Require().Equal(tc.expected.String(), tc.respType.String()) } }) } } func (s *IntegrationTestSuite) TestQueryDelegatorRewardsGRPC() { val := s.network.Validators[0] baseUrl := val.APIAddress rewards, err := sdk.ParseDecCoins("9.8stake") s.Require().NoError(err) testCases := []struct { name string url string headers map[string]string expErr bool respType proto.Message expected proto.Message }{ { "wrong delegator address", fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/rewards", baseUrl, "wrongDelegatorAddress"), map[string]string{}, true, &types.QueryDelegationTotalRewardsResponse{}, nil, }, { "valid request", fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/rewards", baseUrl, val.Address.String()), map[string]string{ grpctypes.GRPCBlockHeightHeader: "2", }, false, &types.QueryDelegationTotalRewardsResponse{}, &types.QueryDelegationTotalRewardsResponse{ Rewards: []types.DelegationDelegatorReward{ types.NewDelegationDelegatorReward(val.ValAddress, rewards), }, Total: rewards, }, }, { "wrong validator address(specific validator rewards)", fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/rewards/%s", baseUrl, val.Address.String(), "wrongValAddress"), map[string]string{}, true, &types.QueryDelegationTotalRewardsResponse{}, nil, }, { "valid request(specific validator rewards)", fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/rewards/%s", baseUrl, val.Address.String(), val.ValAddress.String()), map[string]string{ grpctypes.GRPCBlockHeightHeader: "2", }, false, &types.QueryDelegationRewardsResponse{}, &types.QueryDelegationRewardsResponse{ Rewards: rewards, }, }, } for _, tc := range testCases { tc := tc resp, err := testutil.GetRequestWithHeaders(tc.url, tc.headers) s.Run(tc.name, func() { if tc.expErr { s.Require().Error(val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType)) } else { s.Require().NoError(err) s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType)) s.Require().Equal(tc.expected.String(), tc.respType.String()) } }) } } func (s *IntegrationTestSuite) TestQueryDelegatorValidatorsGRPC() { val := s.network.Validators[0] baseUrl := val.APIAddress testCases := []struct { name string url string expErr bool respType proto.Message expected proto.Message }{ { "empty delegator address", fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/validators", baseUrl, ""), true, &types.QueryDelegatorValidatorsResponse{}, nil, }, { "wrong delegator address", fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/validators", baseUrl, "wrongDelegatorAddress"), true, &types.QueryDelegatorValidatorsResponse{}, nil, }, { "valid request", fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/validators", baseUrl, val.Address.String()), false, &types.QueryDelegatorValidatorsResponse{}, &types.QueryDelegatorValidatorsResponse{ Validators: []string{val.ValAddress.String()}, }, }, } for _, tc := range testCases { tc := tc resp, err := rest.GetRequest(tc.url) s.Run(tc.name, func() { if tc.expErr { s.Require().Error(val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType)) } else { s.Require().NoError(err) s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType)) s.Require().Equal(tc.expected.String(), tc.respType.String()) } }) } } func (s *IntegrationTestSuite) TestQueryWithdrawAddressGRPC() { val := s.network.Validators[0] baseUrl := val.APIAddress testCases := []struct { name string url string expErr bool respType proto.Message expected proto.Message }{ { "empty delegator address", fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/withdraw_address", baseUrl, ""), true, &types.QueryDelegatorWithdrawAddressResponse{}, nil, }, { "wrong delegator address", fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/withdraw_address", baseUrl, "wrongDelegatorAddress"), true, &types.QueryDelegatorWithdrawAddressResponse{}, nil, }, { "valid request", fmt.Sprintf("%s/cosmos/distribution/v1beta1/delegators/%s/withdraw_address", baseUrl, val.Address.String()), false, &types.QueryDelegatorWithdrawAddressResponse{}, &types.QueryDelegatorWithdrawAddressResponse{ WithdrawAddress: val.Address.String(), }, }, } for _, tc := range testCases { tc := tc resp, err := rest.GetRequest(tc.url) s.Run(tc.name, func() { if tc.expErr { s.Require().Error(val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType)) } else { s.Require().NoError(err) s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType)) s.Require().Equal(tc.expected.String(), tc.respType.String()) } }) } } func (s *IntegrationTestSuite) TestQueryValidatorCommunityPoolGRPC() { val := s.network.Validators[0] baseURL := val.APIAddress communityPool, err := sdk.ParseDecCoins("0.4stake") s.Require().NoError(err) testCases := []struct { name string url string headers map[string]string expErr bool respType proto.Message expected proto.Message }{ { "gRPC request params with wrong validator address", fmt.Sprintf("%s/cosmos/distribution/v1beta1/community_pool", baseURL), map[string]string{ grpctypes.GRPCBlockHeightHeader: "2", }, false, &types.QueryCommunityPoolResponse{}, &types.QueryCommunityPoolResponse{ Pool: communityPool, }, }, } for _, tc := range testCases { tc := tc resp, err := testutil.GetRequestWithHeaders(tc.url, tc.headers) s.Run(tc.name, func() { if tc.expErr { s.Require().Error(err) } else { s.Require().NoError(err) s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType)) s.Require().Equal(tc.expected.String(), tc.respType.String()) } }) } } func TestIntegrationTestSuite(t *testing.T) { suite.Run(t, new(IntegrationTestSuite)) }