From b5dc8ec7ce99c5575d1c5a69a3cd9c7fa6607cf2 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Thu, 5 Dec 2024 11:43:55 +0100 Subject: [PATCH 1/5] test(systemtest): fix gRPC tests for v1 & v2 --- systemtests/CHANGELOG.md | 4 + systemtests/rest_support.go | 63 ++++++++--- tests/systemtests/authz_test.go | 142 ++++++++++++------------- tests/systemtests/bank_test.go | 48 ++++----- tests/systemtests/distribution_test.go | 98 ++++++++--------- tests/systemtests/go.mod | 2 + tests/systemtests/go.sum | 2 - 7 files changed, 201 insertions(+), 158 deletions(-) diff --git a/systemtests/CHANGELOG.md b/systemtests/CHANGELOG.md index 77787b91d7a8..b3d09f2fe20e 100644 --- a/systemtests/CHANGELOG.md +++ b/systemtests/CHANGELOG.md @@ -36,6 +36,10 @@ Ref: https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.j ## [Unreleased] +## [v1.0.0-rc.3] - 2024-12-05 + +* [](https://github.com/cosmos/cosmos-sdk/pull/) Add greater than or equal support in Rest test suite + ## [v1.0.0-rc.2] - 2024-11-26 * [#22577](https://github.com/cosmos/cosmos-sdk/pull/22577) Support invalid RPC response for CometBFT v1 diff --git a/systemtests/rest_support.go b/systemtests/rest_support.go index aa7efd807cc4..bfbe5e1a3caf 100644 --- a/systemtests/rest_support.go +++ b/systemtests/rest_support.go @@ -7,15 +7,14 @@ import ( "testing" "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/testutil" ) type RestTestCase struct { - Name string - Url string - ExpCode int - ExpOut string + Name string + Url string + ExpCode int + ExpCodeGTE int + ExpOut string } // RunRestQueries runs given Rest testcases by making requests and @@ -25,25 +24,43 @@ func RunRestQueries(t *testing.T, testCases ...RestTestCase) { for _, tc := range testCases { t.Run(tc.Name, func(t *testing.T) { - resp := GetRequestWithHeaders(t, tc.Url, nil, tc.ExpCode) + if tc.ExpCodeGTE > 0 && tc.ExpCode > 0 { + require.Fail(t, "only one of ExpCode or ExpCodeGTE should be set") + } + + var resp []byte + if tc.ExpCodeGTE > 0 { + resp = GetRequestWithHeadersGreaterThanOrEqual(t, tc.Url, nil, tc.ExpCodeGTE) + } else { + resp = GetRequestWithHeaders(t, tc.Url, nil, tc.ExpCode) + } require.JSONEq(t, tc.ExpOut, string(resp)) }) } } -// TestRestQueryIgnoreNumbers runs given rest testcases by making requests and +// RunRestQueriesIgnoreNumbers runs given rest testcases by making requests and // checking response with expected output ignoring number values // This method is used when number values in response are non-deterministic -func TestRestQueryIgnoreNumbers(t *testing.T, testCases ...RestTestCase) { +func RunRestQueriesIgnoreNumbers(t *testing.T, testCases ...RestTestCase) { t.Helper() for _, tc := range testCases { t.Run(tc.Name, func(t *testing.T) { - resp, err := testutil.GetRequest(tc.Url) - require.NoError(t, err) + if tc.ExpCodeGTE > 0 && tc.ExpCode > 0 { + require.Fail(t, "only one of ExpCode or ExpCodeGTE should be set") + } + + var resp []byte + if tc.ExpCodeGTE > 0 { + resp = GetRequestWithHeadersGreaterThanOrEqual(t, tc.Url, nil, tc.ExpCodeGTE) + } else { + resp = GetRequestWithHeaders(t, tc.Url, nil, tc.ExpCode) + } // regular expression pattern to match any numeric value in the JSON - numberRegexPattern := `"\d+(\.\d+)?"` + // expects when the number is in a word + numberRegexPattern := `"[^"]*"|(\b-?\d+(\.\d+)?\b)` // compile the regex r, err := regexp.Compile(numberRegexPattern) @@ -85,3 +102,25 @@ func GetRequestWithHeaders(t *testing.T, url string, headers map[string]string, return body } + +func GetRequestWithHeadersGreaterThanOrEqual(t *testing.T, url string, headers map[string]string, expCode int) []byte { + t.Helper() + req, err := http.NewRequest("GET", url, nil) + require.NoError(t, err) + + for key, value := range headers { + req.Header.Set(key, value) + } + + httpClient := &http.Client{} + res, err := httpClient.Do(req) + require.NoError(t, err) + defer func() { + _ = res.Body.Close() + }() + body, err := io.ReadAll(res.Body) + require.NoError(t, err) + require.GreaterOrEqual(t, res.StatusCode, expCode, "status code should be greater or equal to %d, got: %d, %s", expCode, res.StatusCode, body) + + return body +} diff --git a/tests/systemtests/authz_test.go b/tests/systemtests/authz_test.go index 902b6631e8f8..9e6f117bb905 100644 --- a/tests/systemtests/authz_test.go +++ b/tests/systemtests/authz_test.go @@ -682,78 +682,78 @@ func TestAuthzGRPCQueries(t *testing.T) { grantTestCases := []systest.RestTestCase{ { - "invalid granter address", - fmt.Sprintf(grantURL, "invalid_granter", grantee1Addr, msgSendTypeURL), - http.StatusInternalServerError, - bech32FailOutput, + Name: "invalid granter address", + Url: fmt.Sprintf(grantURL, "invalid_granter", grantee1Addr, msgSendTypeURL), + ExpCodeGTE: http.StatusBadRequest, + ExpOut: bech32FailOutput, }, { - "invalid grantee address", - fmt.Sprintf(grantURL, granterAddr, "invalid_grantee", msgSendTypeURL), - http.StatusInternalServerError, - bech32FailOutput, + Name: "invalid grantee address", + Url: fmt.Sprintf(grantURL, granterAddr, "invalid_grantee", msgSendTypeURL), + ExpCodeGTE: http.StatusBadRequest, + ExpOut: bech32FailOutput, }, { - "with empty granter", - fmt.Sprintf(grantURL, "", grantee1Addr, msgSendTypeURL), - http.StatusInternalServerError, - emptyStrOutput, + Name: "with empty granter", + Url: fmt.Sprintf(grantURL, "", grantee1Addr, msgSendTypeURL), + ExpCodeGTE: http.StatusBadRequest, + ExpOut: emptyStrOutput, }, { - "with empty grantee", - fmt.Sprintf(grantURL, granterAddr, "", msgSendTypeURL), - http.StatusInternalServerError, - emptyStrOutput, + Name: "with empty grantee", + Url: fmt.Sprintf(grantURL, granterAddr, "", msgSendTypeURL), + ExpCodeGTE: http.StatusBadRequest, + ExpOut: emptyStrOutput, }, { - "invalid msg-type", - fmt.Sprintf(grantURL, granterAddr, grantee1Addr, "invalidMsg"), - http.StatusInternalServerError, - invalidMsgTypeOutput, + Name: "invalid msg-type", + Url: fmt.Sprintf(grantURL, granterAddr, grantee1Addr, "invalidMsg"), + ExpCode: http.StatusInternalServerError, + ExpOut: invalidMsgTypeOutput, }, { - "valid grant query", - fmt.Sprintf(grantURL, granterAddr, grantee1Addr, msgSendTypeURL), - http.StatusOK, - expGrantOutput, + Name: "valid grant query", + Url: fmt.Sprintf(grantURL, granterAddr, grantee1Addr, msgSendTypeURL), + ExpCode: http.StatusOK, + ExpOut: expGrantOutput, }, } - systest.RunRestQueries(t, grantTestCases...) + systest.RunRestQueriesIgnoreNumbers(t, grantTestCases...) // test query grants grpc endpoint grantsURL := baseurl + "/cosmos/authz/v1beta1/grants?granter=%s&grantee=%s" grantsTestCases := []systest.RestTestCase{ { - "expect single grant", - fmt.Sprintf(grantsURL, granterAddr, grantee1Addr), - http.StatusOK, - fmt.Sprintf(`{"grants":[{%s}],"pagination":{"next_key":null,"total":"1"}}`, grant1), + Name: "expect single grant", + Url: fmt.Sprintf(grantsURL, granterAddr, grantee1Addr), + ExpCode: http.StatusOK, + ExpOut: fmt.Sprintf(`{"grants":[{%s}],"pagination":{"next_key":null,"total":"1"}}`, grant1), }, { - "expect two grants", - fmt.Sprintf(grantsURL, granterAddr, grantee2Addr), - http.StatusOK, - fmt.Sprintf(`{"grants":[{%s},{%s}],"pagination":{"next_key":null,"total":"2"}}`, grant2, grant3), + Name: "expect two grants", + Url: fmt.Sprintf(grantsURL, granterAddr, grantee2Addr), + ExpCode: http.StatusOK, + ExpOut: fmt.Sprintf(`{"grants":[{%s},{%s}],"pagination":{"next_key":null,"total":"2"}}`, grant2, grant3), }, { - "expect single grant with pagination", - fmt.Sprintf(grantsURL+"&pagination.limit=1", granterAddr, grantee2Addr), - http.StatusOK, - fmt.Sprintf(`{"grants":[{%s}],"pagination":{"next_key":"L2Nvc21vcy5nb3YudjEuTXNnVm90ZQ==","total":"0"}}`, grant2), + Name: "expect single grant with pagination", + Url: fmt.Sprintf(grantsURL+"&pagination.limit=1", granterAddr, grantee2Addr), + ExpCode: http.StatusOK, + ExpOut: fmt.Sprintf(`{"grants":[{%s}],"pagination":{"next_key":"L2Nvc21vcy5nb3YudjEuTXNnVm90ZQ==","total":"0"}}`, grant2), }, { - "expect single grant with pagination limit and offset", - fmt.Sprintf(grantsURL+"&pagination.limit=1&pagination.offset=1", granterAddr, grantee2Addr), - http.StatusOK, - fmt.Sprintf(`{"grants":[{%s}],"pagination":{"next_key":null,"total":"0"}}`, grant3), + Name: "expect single grant with pagination limit and offset", + Url: fmt.Sprintf(grantsURL+"&pagination.limit=1&pagination.offset=1", granterAddr, grantee2Addr), + ExpCode: http.StatusOK, + ExpOut: fmt.Sprintf(`{"grants":[{%s}],"pagination":{"next_key":null,"total":"0"}}`, grant3), }, { - "expect two grants with pagination", - fmt.Sprintf(grantsURL+"&pagination.limit=2", granterAddr, grantee2Addr), - http.StatusOK, - fmt.Sprintf(`{"grants":[{%s},{%s}],"pagination":{"next_key":null,"total":"0"}}`, grant2, grant3), + Name: "expect two grants with pagination", + Url: fmt.Sprintf(grantsURL+"&pagination.limit=2", granterAddr, grantee2Addr), + ExpCode: http.StatusOK, + ExpOut: fmt.Sprintf(`{"grants":[{%s},{%s}],"pagination":{"next_key":null,"total":"0"}}`, grant2, grant3), }, } @@ -768,26 +768,26 @@ func TestAuthzGRPCQueries(t *testing.T) { granterTestCases := []systest.RestTestCase{ { - "invalid granter account address", - fmt.Sprintf(grantsByGranterURL, "invalid address"), - http.StatusInternalServerError, - decodingFailedOutput, + Name: "invalid granter account address", + Url: fmt.Sprintf(grantsByGranterURL, "invalid address"), + ExpCodeGTE: http.StatusBadRequest, + ExpOut: decodingFailedOutput, }, { - "no authorizations found from granter", - fmt.Sprintf(grantsByGranterURL, grantee2Addr), - http.StatusOK, - noAuthorizationsOutput, + Name: "no authorizations found from granter", + Url: fmt.Sprintf(grantsByGranterURL, grantee2Addr), + ExpCode: http.StatusOK, + ExpOut: noAuthorizationsOutput, }, { - "valid granter query", - fmt.Sprintf(grantsByGranterURL, grantee1Addr), - http.StatusOK, - granterQueryOutput, + Name: "valid granter query", + Url: fmt.Sprintf(grantsByGranterURL, grantee1Addr), + ExpCode: http.StatusOK, + ExpOut: granterQueryOutput, }, } - systest.RunRestQueries(t, granterTestCases...) + systest.RunRestQueriesIgnoreNumbers(t, granterTestCases...) // test query grants by grantee grpc endpoint grantsByGranteeURL := baseurl + "/cosmos/authz/v1beta1/grants/grantee/%s" @@ -795,26 +795,26 @@ func TestAuthzGRPCQueries(t *testing.T) { granteeTestCases := []systest.RestTestCase{ { - "invalid grantee account address", - fmt.Sprintf(grantsByGranteeURL, "invalid address"), - http.StatusInternalServerError, - decodingFailedOutput, + Name: "invalid grantee account address", + Url: fmt.Sprintf(grantsByGranteeURL, "invalid address"), + ExpCodeGTE: http.StatusBadRequest, + ExpOut: decodingFailedOutput, }, { - "no authorizations found from grantee", - fmt.Sprintf(grantsByGranteeURL, granterAddr), - http.StatusOK, - noAuthorizationsOutput, + Name: "no authorizations found from grantee", + Url: fmt.Sprintf(grantsByGranteeURL, granterAddr), + ExpCode: http.StatusOK, + ExpOut: noAuthorizationsOutput, }, { - "valid grantee query", - fmt.Sprintf(grantsByGranteeURL, grantee1Addr), - http.StatusOK, - grantee1GrantsOutput, + Name: "valid grantee query", + Url: fmt.Sprintf(grantsByGranteeURL, grantee1Addr), + ExpCode: http.StatusOK, + ExpOut: grantee1GrantsOutput, }, } - systest.RunRestQueries(t, granteeTestCases...) + systest.RunRestQueriesIgnoreNumbers(t, granteeTestCases...) } func setupChain(t *testing.T) (*systest.CLIWrapper, string, string) { diff --git a/tests/systemtests/bank_test.go b/tests/systemtests/bank_test.go index 1171e1466ab8..38f0dc2f8372 100644 --- a/tests/systemtests/bank_test.go +++ b/tests/systemtests/bank_test.go @@ -289,22 +289,22 @@ func TestBankGRPCQueries(t *testing.T) { denomMetadataUrl := baseurl + "/cosmos/bank/v1beta1/denoms_metadata" dmTestCases := []systest.RestTestCase{ { - "test GRPC client metadata", - denomMetadataUrl, - http.StatusOK, - fmt.Sprintf(`{"metadatas":%s,"pagination":{"next_key":null,"total":"2"}}`, bankDenomMetadata), + Name: "test GRPC client metadata", + Url: denomMetadataUrl, + ExpCode: http.StatusOK, + ExpOut: fmt.Sprintf(`{"metadatas":%s,"pagination":{"next_key":null,"total":"2"}}`, bankDenomMetadata), }, { - "test GRPC client metadata of a specific denom", - denomMetadataUrl + "/uatom", - http.StatusOK, - fmt.Sprintf(`{"metadata":%s}`, atomDenomMetadata), + Name: "test GRPC client metadata of a specific denom", + Url: denomMetadataUrl + "/uatom", + ExpCode: http.StatusOK, + ExpOut: fmt.Sprintf(`{"metadata":%s}`, atomDenomMetadata), }, { - "test GRPC client metadata of a bogus denom", - denomMetadataUrl + "/foobar", - http.StatusNotFound, - `{"code":5, "message":"client metadata for denom foobar", "details":[]}`, + Name: "test GRPC client metadata of a bogus denom", + Url: denomMetadataUrl + "/foobar", + ExpCode: http.StatusNotFound, + ExpOut: `{"code":5, "message":"client metadata for denom foobar", "details":[]}`, }, } @@ -316,22 +316,22 @@ func TestBankGRPCQueries(t *testing.T) { balanceTestCases := []systest.RestTestCase{ { - "test GRPC total account balance", - balanceUrl + account1Addr, - http.StatusOK, - allBalancesOutput, + Name: "test GRPC total account balance", + Url: balanceUrl + account1Addr, + ExpCode: http.StatusOK, + ExpOut: allBalancesOutput, }, { - "test GRPC account balance of a specific denom", - fmt.Sprintf("%s%s/by_denom?denom=%s", balanceUrl, account1Addr, newDenom), - http.StatusOK, - fmt.Sprintf(`{"balance":%s}`, specificDenomOutput), + Name: "test GRPC account balance of a specific denom", + Url: fmt.Sprintf("%s%s/by_denom?denom=%s", balanceUrl, account1Addr, newDenom), + ExpCode: http.StatusOK, + ExpOut: fmt.Sprintf(`{"balance":%s}`, specificDenomOutput), }, { - "test GRPC account balance of a bogus denom", - fmt.Sprintf("%s%s/by_denom?denom=foobar", balanceUrl, account1Addr), - http.StatusOK, - fmt.Sprintf(`{"balance":%s}`, bogusDenomOutput), + Name: "test GRPC account balance of a bogus denom", + Url: fmt.Sprintf("%s%s/by_denom?denom=foobar", balanceUrl, account1Addr), + ExpCode: http.StatusOK, + ExpOut: fmt.Sprintf(`{"balance":%s}`, bogusDenomOutput), }, } diff --git a/tests/systemtests/distribution_test.go b/tests/systemtests/distribution_test.go index 7e40589bf5da..495fd5807e81 100644 --- a/tests/systemtests/distribution_test.go +++ b/tests/systemtests/distribution_test.go @@ -129,10 +129,10 @@ func TestDistrValidatorGRPCQueries(t *testing.T) { paramsTestCases := []systest.RestTestCase{ { - "gRPC request params", - paramsURL, - http.StatusOK, - `{"params":{"community_tax":"0.020000000000000000","base_proposer_reward":"0.000000000000000000","bonus_proposer_reward":"0.000000000000000000","withdraw_addr_enabled":true}}`, + Name: "gRPC request params", + Url: paramsURL, + ExpCode: http.StatusOK, + ExpOut: `{"params":{"community_tax":"0.020000000000000000","base_proposer_reward":"0.000000000000000000","bonus_proposer_reward":"0.000000000000000000","withdraw_addr_enabled":true}}`, }, } systest.RunRestQueries(t, paramsTestCases...) @@ -143,39 +143,39 @@ func TestDistrValidatorGRPCQueries(t *testing.T) { validatorsTestCases := []systest.RestTestCase{ { - "gRPC request validator with valid validator address", - fmt.Sprintf(validatorsURL, valOperAddr), - http.StatusOK, - validatorsOutput, + Name: "gRPC request validator with valid validator address", + Url: fmt.Sprintf(validatorsURL, valOperAddr), + ExpCode: http.StatusOK, + ExpOut: validatorsOutput, }, } - systest.TestRestQueryIgnoreNumbers(t, validatorsTestCases...) + systest.RunRestQueriesIgnoreNumbers(t, validatorsTestCases...) // test outstanding rewards grpc endpoint outstandingRewardsURL := baseurl + `/cosmos/distribution/v1beta1/validators/%s/outstanding_rewards` rewardsTestCases := []systest.RestTestCase{ { - "gRPC request outstanding rewards with valid validator address", - fmt.Sprintf(outstandingRewardsURL, valOperAddr), - http.StatusOK, - fmt.Sprintf(`{"rewards":{"rewards":[%s]}}`, expectedAmountOutput), + Name: "gRPC request outstanding rewards with valid validator address", + Url: fmt.Sprintf(outstandingRewardsURL, valOperAddr), + ExpCode: http.StatusOK, + ExpOut: fmt.Sprintf(`{"rewards":{"rewards":[%s]}}`, expectedAmountOutput), }, } - systest.TestRestQueryIgnoreNumbers(t, rewardsTestCases...) + systest.RunRestQueriesIgnoreNumbers(t, rewardsTestCases...) // test validator commission grpc endpoint commissionURL := baseurl + `/cosmos/distribution/v1beta1/validators/%s/commission` commissionTestCases := []systest.RestTestCase{ { - "gRPC request commission with valid validator address", - fmt.Sprintf(commissionURL, valOperAddr), - http.StatusOK, - fmt.Sprintf(`{"commission":{"commission":[%s]}}`, expectedAmountOutput), + Name: "gRPC request commission with valid validator address", + Url: fmt.Sprintf(commissionURL, valOperAddr), + ExpCode: http.StatusOK, + ExpOut: fmt.Sprintf(`{"commission":{"commission":[%s]}}`, expectedAmountOutput), }, } - systest.TestRestQueryIgnoreNumbers(t, commissionTestCases...) + systest.RunRestQueriesIgnoreNumbers(t, commissionTestCases...) // test validator slashes grpc endpoint slashURL := baseurl + `/cosmos/distribution/v1beta1/validators/%s/slashes` @@ -183,25 +183,25 @@ func TestDistrValidatorGRPCQueries(t *testing.T) { slashTestCases := []systest.RestTestCase{ { - "invalid start height", - fmt.Sprintf(slashURL+`?starting_height=%s&ending_height=%s`, valOperAddr, "-3", "3"), - http.StatusBadRequest, - invalidHeightOutput, + Name: "invalid start height", + Url: fmt.Sprintf(slashURL+`?starting_height=%s&ending_height=%s`, valOperAddr, "-3", "3"), + ExpCode: http.StatusBadRequest, + ExpOut: invalidHeightOutput, }, { - "invalid end height", - fmt.Sprintf(slashURL+`?starting_height=%s&ending_height=%s`, valOperAddr, "1", "-3"), - http.StatusBadRequest, - invalidHeightOutput, + Name: "invalid end height", + Url: fmt.Sprintf(slashURL+`?starting_height=%s&ending_height=%s`, valOperAddr, "1", "-3"), + ExpCode: http.StatusBadRequest, + ExpOut: invalidHeightOutput, }, { - "valid request get slashes", - fmt.Sprintf(slashURL+`?starting_height=%s&ending_height=%s`, valOperAddr, "1", "3"), - http.StatusOK, - `{"slashes":[],"pagination":{"next_key":null,"total":"0"}}`, + Name: "valid request get slashes", + Url: fmt.Sprintf(slashURL+`?starting_height=%s&ending_height=%s`, valOperAddr, "1", "3"), + ExpCode: http.StatusOK, + ExpOut: `{"slashes":[],"pagination":{"next_key":null,"total":"0"}}`, }, } - systest.RunRestQueries(t, slashTestCases...) + systest.RunRestQueriesIgnoreNumbers(t, slashTestCases...) } func TestDistrDelegatorGRPCQueries(t *testing.T) { @@ -257,28 +257,28 @@ func TestDistrDelegatorGRPCQueries(t *testing.T) { delegatorRewardsTestCases := []systest.RestTestCase{ { - "valid rewards request with valid delegator address", - fmt.Sprintf(delegatorRewardsURL, delAddr), - http.StatusOK, - rewardsOutput, + Name: "valid rewards request with valid delegator address", + Url: fmt.Sprintf(delegatorRewardsURL, delAddr), + ExpCode: http.StatusOK, + ExpOut: rewardsOutput, }, { - "valid request(specific validator rewards)", - fmt.Sprintf(delegatorRewardsURL+`/%s`, delAddr, valOperAddr), - http.StatusOK, - fmt.Sprintf(`{"rewards":[%s]}`, expectedAmountOutput), + Name: "valid request(specific validator rewards)", + Url: fmt.Sprintf(delegatorRewardsURL+`/%s`, delAddr, valOperAddr), + ExpCode: http.StatusOK, + ExpOut: fmt.Sprintf(`{"rewards":[%s]}`, expectedAmountOutput), }, } - systest.TestRestQueryIgnoreNumbers(t, delegatorRewardsTestCases...) + systest.RunRestQueriesIgnoreNumbers(t, delegatorRewardsTestCases...) // test delegator validators grpc endpoint delegatorValsURL := baseurl + `/cosmos/distribution/v1beta1/delegators/%s/validators` valsTestCases := []systest.RestTestCase{ { - "gRPC request delegator validators with valid delegator address", - fmt.Sprintf(delegatorValsURL, delAddr), - http.StatusOK, - fmt.Sprintf(`{"validators":["%s"]}`, valOperAddr), + Name: "gRPC request delegator validators with valid delegator address", + Url: fmt.Sprintf(delegatorValsURL, delAddr), + ExpCode: http.StatusOK, + ExpOut: fmt.Sprintf(`{"validators":["%s"]}`, valOperAddr), }, } systest.RunRestQueries(t, valsTestCases...) @@ -287,10 +287,10 @@ func TestDistrDelegatorGRPCQueries(t *testing.T) { withdrawAddrURL := baseurl + `/cosmos/distribution/v1beta1/delegators/%s/withdraw_address` withdrawAddrTestCases := []systest.RestTestCase{ { - "gRPC request withdraw address with valid delegator address", - fmt.Sprintf(withdrawAddrURL, delAddr), - http.StatusOK, - fmt.Sprintf(`{"withdraw_address":"%s"}`, delAddr), + Name: "gRPC request withdraw address with valid delegator address", + Url: fmt.Sprintf(withdrawAddrURL, delAddr), + ExpCode: http.StatusOK, + ExpOut: fmt.Sprintf(`{"withdraw_address":"%s"}`, delAddr), }, } systest.RunRestQueries(t, withdrawAddrTestCases...) diff --git a/tests/systemtests/go.mod b/tests/systemtests/go.mod index 6608500045bb..0c841fc84099 100644 --- a/tests/systemtests/go.mod +++ b/tests/systemtests/go.mod @@ -2,6 +2,8 @@ module github.com/cosmos/cosmos-sdk/tests/systemtests go 1.23 +replace cosmossdk.io/systemtests => ../../systemtests + require ( cosmossdk.io/math v1.4.0 cosmossdk.io/systemtests v1.0.0-rc.1.0.20241128092904-215d5c16f64d diff --git a/tests/systemtests/go.sum b/tests/systemtests/go.sum index e5b744073877..14236260fe80 100644 --- a/tests/systemtests/go.sum +++ b/tests/systemtests/go.sum @@ -16,8 +16,6 @@ cosmossdk.io/math v1.4.0 h1:XbgExXFnXmF/CccPPEto40gOO7FpWu9yWNAZPN3nkNQ= cosmossdk.io/math v1.4.0/go.mod h1:O5PkD4apz2jZs4zqFdTr16e1dcaQCc5z6lkEnrrppuk= cosmossdk.io/store v1.1.0 h1:LnKwgYMc9BInn9PhpTFEQVbL9UK475G2H911CGGnWHk= cosmossdk.io/store v1.1.0/go.mod h1:oZfW/4Fc/zYqu3JmQcQdUJ3fqu5vnYTn3LZFFy8P8ng= -cosmossdk.io/systemtests v1.0.0-rc.1.0.20241128092904-215d5c16f64d h1:zZUt9DD+3qvwnpQHPwYJ5+NEUU4wMFeNpPBegWMfbn8= -cosmossdk.io/systemtests v1.0.0-rc.1.0.20241128092904-215d5c16f64d/go.mod h1:ME2eFY/+2CjaFrPOMW8paPXupMzYaDMTKQ1sRvi71hU= cosmossdk.io/x/tx v0.13.3-0.20240419091757-db5906b1e894 h1:kHEvzVqpNv/9pnaEPBsgE/FMc+cVmWjSsInRufkZkpQ= cosmossdk.io/x/tx v0.13.3-0.20240419091757-db5906b1e894/go.mod h1:Tb6/tpONmtL5qFdOMdv1pdvrtJNxcazZBoz04HB71ss= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= From 7ad3bf03573a93450cd5b59a6a80f8cf06c7a525 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Thu, 5 Dec 2024 12:07:20 +0100 Subject: [PATCH 2/5] cl --- systemtests/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/systemtests/CHANGELOG.md b/systemtests/CHANGELOG.md index b3d09f2fe20e..2a27c4162cf2 100644 --- a/systemtests/CHANGELOG.md +++ b/systemtests/CHANGELOG.md @@ -38,7 +38,7 @@ Ref: https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.j ## [v1.0.0-rc.3] - 2024-12-05 -* [](https://github.com/cosmos/cosmos-sdk/pull/) Add greater than or equal support in Rest test suite +* [#22774](https://github.com/cosmos/cosmos-sdk/pull/22774) Add greater than or equal support in Rest test suite ## [v1.0.0-rc.2] - 2024-11-26 From c27ab2bf77e7309b36ebddf66fb8a838d11ce39b Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Thu, 5 Dec 2024 15:32:05 +0100 Subject: [PATCH 3/5] fix regex --- systemtests/rest_support.go | 42 +++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/systemtests/rest_support.go b/systemtests/rest_support.go index bfbe5e1a3caf..b2615fc2aed6 100644 --- a/systemtests/rest_support.go +++ b/systemtests/rest_support.go @@ -45,6 +45,35 @@ func RunRestQueries(t *testing.T, testCases ...RestTestCase) { func RunRestQueriesIgnoreNumbers(t *testing.T, testCases ...RestTestCase) { t.Helper() + // regex for standalone quoted numbers (e.g., "-3" or "0.02") + standaloneQuotedNumberRegex := regexp.MustCompile(`"(-?\d+(\.\d+)?)"`) + // regex for numbers in escaped strings (e.g., \"-3\") + escapedNumberRegex := regexp.MustCompile(`\\\"(-?\d+(\.\d+)?)\\\"`) + // regex for unquoted numbers (e.g., 2, -1, 0.02,) + unquotedNumberRegex := regexp.MustCompile(`\b-?\d+(\.\d+)?\b,`) + + replaceNumber := func(input string) string { + // handle numbers in escaped strings + result := escapedNumberRegex.ReplaceAllStringFunc(input, func(match string) string { + // replace with escaped "NUMBER" + return `\"NUMBER\"` + }) + + // handle standalone quoted numbers + result = standaloneQuotedNumberRegex.ReplaceAllStringFunc(result, func(match string) string { + // replace with "NUMBER" (quotes preserved) + return `"NUMBER"` + }) + + // handle unquoted numbers + result = unquotedNumberRegex.ReplaceAllStringFunc(result, func(match string) string { + // replace with "NUMBER" (add quotes to ensure json validity) + return `"NUMBER",` + }) + + return result + } + for _, tc := range testCases { t.Run(tc.Name, func(t *testing.T) { if tc.ExpCodeGTE > 0 && tc.ExpCode > 0 { @@ -58,17 +87,8 @@ func RunRestQueriesIgnoreNumbers(t *testing.T, testCases ...RestTestCase) { resp = GetRequestWithHeaders(t, tc.Url, nil, tc.ExpCode) } - // regular expression pattern to match any numeric value in the JSON - // expects when the number is in a word - numberRegexPattern := `"[^"]*"|(\b-?\d+(\.\d+)?\b)` - - // compile the regex - r, err := regexp.Compile(numberRegexPattern) - require.NoError(t, err) - - // replace all numeric values in the above JSONs with `NUMBER` text - expectedJSON := r.ReplaceAllString(tc.ExpOut, `"NUMBER"`) - actualJSON := r.ReplaceAllString(string(resp), `"NUMBER"`) + expectedJSON := replaceNumber(tc.ExpOut) + actualJSON := replaceNumber(string(resp)) // compare two jsons require.JSONEq(t, expectedJSON, actualJSON) From af3d1622bc6cbb3c757d4eb57314e7647b4a9cf8 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Thu, 5 Dec 2024 15:37:26 +0100 Subject: [PATCH 4/5] fixes --- server/v2/appmanager/appmanager.go | 2 +- tests/systemtests/bank_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/v2/appmanager/appmanager.go b/server/v2/appmanager/appmanager.go index b31bd33db977..19f7eaae545c 100644 --- a/server/v2/appmanager/appmanager.go +++ b/server/v2/appmanager/appmanager.go @@ -230,7 +230,7 @@ func (a appManager[T]) Query(ctx context.Context, version uint64, request transa _, queryState, err = a.db.StateLatest() } if err != nil { - return nil, err + return nil, fmt.Errorf("invalid height: %w", err) } return a.stf.Query(ctx, queryState, a.config.QueryGasLimit, request) } diff --git a/tests/systemtests/bank_test.go b/tests/systemtests/bank_test.go index 38f0dc2f8372..c5c45bca6d63 100644 --- a/tests/systemtests/bank_test.go +++ b/tests/systemtests/bank_test.go @@ -265,7 +265,7 @@ func TestBankGRPCQueries(t *testing.T) { map[string]string{ blockHeightHeader: fmt.Sprintf("%d", blockHeight+5), }, - http.StatusInternalServerError, + http.StatusBadRequest, "invalid height", }, { @@ -280,7 +280,7 @@ func TestBankGRPCQueries(t *testing.T) { for _, tc := range supplyTestCases { t.Run(tc.name, func(t *testing.T) { - resp := systest.GetRequestWithHeaders(t, tc.url, tc.headers, tc.expHttpCode) + resp := systest.GetRequestWithHeadersGreaterThanOrEqual(t, tc.url, tc.headers, tc.expHttpCode) require.Contains(t, string(resp), tc.expOut) }) } From 0dee68759bc2b3afa1524f8171d5ed5a4bec8b4a Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Thu, 5 Dec 2024 15:58:21 +0100 Subject: [PATCH 5/5] use pseudo version --- tests/systemtests/go.mod | 4 +--- tests/systemtests/go.sum | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/systemtests/go.mod b/tests/systemtests/go.mod index 461a3ab622d3..0305bff6e11e 100644 --- a/tests/systemtests/go.mod +++ b/tests/systemtests/go.mod @@ -2,11 +2,9 @@ module github.com/cosmos/cosmos-sdk/tests/systemtests go 1.23 -replace cosmossdk.io/systemtests => ../../systemtests - require ( cosmossdk.io/math v1.4.0 - cosmossdk.io/systemtests v1.0.0-rc.1.0.20241128092904-215d5c16f64d + cosmossdk.io/systemtests v1.0.0-rc.2.0.20241205143753-9e94ea87f6e4 github.com/cosmos/cosmos-sdk v0.50.6 ) diff --git a/tests/systemtests/go.sum b/tests/systemtests/go.sum index be0988856648..8c0abace40bd 100644 --- a/tests/systemtests/go.sum +++ b/tests/systemtests/go.sum @@ -16,6 +16,8 @@ cosmossdk.io/math v1.4.0 h1:XbgExXFnXmF/CccPPEto40gOO7FpWu9yWNAZPN3nkNQ= cosmossdk.io/math v1.4.0/go.mod h1:O5PkD4apz2jZs4zqFdTr16e1dcaQCc5z6lkEnrrppuk= cosmossdk.io/store v1.1.0 h1:LnKwgYMc9BInn9PhpTFEQVbL9UK475G2H911CGGnWHk= cosmossdk.io/store v1.1.0/go.mod h1:oZfW/4Fc/zYqu3JmQcQdUJ3fqu5vnYTn3LZFFy8P8ng= +cosmossdk.io/systemtests v1.0.0-rc.2.0.20241205143753-9e94ea87f6e4 h1:gt0rrxBW4x9KM3+ES8Gy5BZbKIHI3AspYEuvWZO6fgU= +cosmossdk.io/systemtests v1.0.0-rc.2.0.20241205143753-9e94ea87f6e4/go.mod h1:B3RY1tY/iwLjQ9MUTz+GsiXV9gEdS8mfUvSQtWUwaAo= cosmossdk.io/x/tx v0.13.3-0.20240419091757-db5906b1e894 h1:kHEvzVqpNv/9pnaEPBsgE/FMc+cVmWjSsInRufkZkpQ= cosmossdk.io/x/tx v0.13.3-0.20240419091757-db5906b1e894/go.mod h1:Tb6/tpONmtL5qFdOMdv1pdvrtJNxcazZBoz04HB71ss= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=