Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(systemtests): fix gRPC tests for v1 & v2 #22774

Merged
merged 6 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions systemtests/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

* [#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

* [#22577](https://github.com/cosmos/cosmos-sdk/pull/22577) Support invalid RPC response for CometBFT v1
Expand Down
63 changes: 51 additions & 12 deletions systemtests/rest_support.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@
"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
Expand All @@ -25,25 +24,43 @@

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)
Expand Down Expand Up @@ -85,3 +102,25 @@

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)
}
Comment on lines +131 to +133

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism

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
}
julienrbrt marked this conversation as resolved.
Show resolved Hide resolved
142 changes: 71 additions & 71 deletions tests/systemtests/authz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
},
}

Expand All @@ -768,53 +768,53 @@ 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"
grantee1GrantsOutput := fmt.Sprintf(`{"grants":[{"granter":"%s","grantee":"%s",%s}],"pagination":{"next_key":null,"total":"1"}}`, granterAddr, grantee1Addr, grant1)

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) {
Expand Down
48 changes: 24 additions & 24 deletions tests/systemtests/bank_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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":[]}`,
},
}

Expand All @@ -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),
},
}

Expand Down
Loading
Loading