From ee781223649c7910435a5e8c899e6bf978487dad Mon Sep 17 00:00:00 2001 From: Milan Mulji <98309852+mmulji-ic@users.noreply.github.com> Date: Mon, 30 Jan 2023 13:33:51 +0100 Subject: [PATCH] Reintroduce missing code for rest endpoint wiring (#2080) * Reintroduce missing code for rest endpoint wiring * Fix gofumpt * e2e test to check if endpoints are available * Ran linter/formater * Refactor and add comprehensive tests for missing routes (#2094) * Fixed var -> const definition --------- Co-authored-by: lg Co-authored-by: lg <8335464+glnro@users.noreply.github.com> (cherry picked from commit 690f167fc25923e50f5cbcbafbc3300238efc084) --- app/app.go | 6 ++ tests/e2e/e2e_rest_regression_test.go | 89 +++++++++++++++++++++++++++ tests/e2e/e2e_test.go | 8 +++ tests/e2e/http_util.go | 18 ++++++ 4 files changed, 121 insertions(+) create mode 100644 tests/e2e/e2e_rest_regression_test.go diff --git a/app/app.go b/app/app.go index 5d744b227b7..78455444069 100644 --- a/app/app.go +++ b/app/app.go @@ -10,6 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" + "github.com/cosmos/cosmos-sdk/client/rpc" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/server/api" @@ -20,6 +21,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/x/auth/ante" + authrest "github.com/cosmos/cosmos-sdk/x/auth/client/rest" authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/crisis" @@ -319,12 +321,16 @@ func (app *GaiaApp) SimulationManager() *module.SimulationManager { // API server. func (app *GaiaApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) { clientCtx := apiSvr.ClientCtx + rpc.RegisterRoutes(clientCtx, apiSvr.Router) + // Register legacy tx routes. + authrest.RegisterTxRoutes(clientCtx, apiSvr.Router) // Register new tx routes from grpc-gateway. authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) // Register new tendermint queries routes from grpc-gateway. tmservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) // Register legacy and grpc-gateway routes for all modules. + ModuleBasics.RegisterRESTRoutes(clientCtx, apiSvr.Router) ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) // register swagger API from root so that other applications can override easily diff --git a/tests/e2e/e2e_rest_regression_test.go b/tests/e2e/e2e_rest_regression_test.go new file mode 100644 index 00000000000..8777c516a69 --- /dev/null +++ b/tests/e2e/e2e_rest_regression_test.go @@ -0,0 +1,89 @@ +package e2e + +import ( + "fmt" + "net/http" +) + +/* +RestRegression tests the continuity of critical endpoints that node operators, block explorers, and ecosystem participants depend on. +Test Node REST Endpoints: +1. http://host:1317/validatorsets/latest +2. http://host:1317/validatorsets/{height} +3. http://host:1317/blocks/latest +4. http://host:1317/blocks/{height} +5. http://host:1317/syncing +6. http://host:1317/node_info +7. http://host:1317/txs +Test Module REST Endpoints +1. Bank total +2. Auth params +3. Distribution for Community Pool +4. Evidence +5. Gov proposals +6. Mint params +7. Slashing params +8. Staking params +*/ + +const ( + valSetLatestPath = "/validatorsets/latest" + valSetHeightPath = "/validatorsets/1" + blocksLatestPath = "/blocks/latest" + blocksHeightPath = "/blocks/1" + syncingPath = "/syncing" + nodeInfoPath = "/node_info" + transactionsPath = "/txs" + bankTotalModuleQueryPath = "/bank/total" + authParamsModuleQueryPath = "/auth/params" + distributionCommPoolModuleQueryPath = "/distribution/community_pool" + evidenceModuleQueryPath = "/evidence" + govPropsModuleQueryPath = "/gov/proposals" + mintingParamsModuleQueryPath = "/minting/parameters" + slashingParamsModuleQueryPath = "/slashing/parameters" + stakingParamsModuleQueryPath = "/staking/parameters" + missingPath = "/missing_endpoint" +) + +func (s *IntegrationTestSuite) testRestInterfaces() { + s.Run("test rest interfaces", func() { + var ( + valIdx = 0 + c = s.chainA + endpointURL = fmt.Sprintf("http://%s", s.valResources[c.id][valIdx].GetHostPort("1317/tcp")) + testEndpoints = []struct { + Path string + ExpectedStatus int + }{ + // Client Endpoints + {nodeInfoPath, 200}, + {syncingPath, 200}, + {valSetLatestPath, 200}, + {valSetHeightPath, 200}, + {blocksLatestPath, 200}, + {blocksHeightPath, 200}, + {transactionsPath, 200}, + // Module Endpoints + {bankTotalModuleQueryPath, 200}, + {authParamsModuleQueryPath, 200}, + {distributionCommPoolModuleQueryPath, 200}, + {evidenceModuleQueryPath, 200}, + {govPropsModuleQueryPath, 200}, + {mintingParamsModuleQueryPath, 200}, + {slashingParamsModuleQueryPath, 200}, + {stakingParamsModuleQueryPath, 200}, + {missingPath, 501}, + } + ) + + for _, endpoint := range testEndpoints { + resp, err := http.Get(fmt.Sprintf("%s%s", endpointURL, endpoint.Path)) + s.NoError(err, fmt.Sprintf("failed to get endpoint: %s%s", endpointURL, endpoint.Path)) + + _, err = readJSON(resp) + s.NoError(err, fmt.Sprintf("failed to read body of endpoint: %s%s", endpointURL, endpoint.Path)) + + s.EqualValues(resp.StatusCode, endpoint.ExpectedStatus) + } + }) +} diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index c0630ae4d7a..f272d72434c 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -16,8 +16,16 @@ var ( runSlashingTest = true runStakingAndDistributionTest = true runVestingTest = true + runRestInterfacesTest = true ) +func (s *IntegrationTestSuite) TestRestInterfaces() { + if !runRestInterfacesTest { + s.T().Skip() + } + s.testRestInterfaces() +} + func (s *IntegrationTestSuite) TestBank() { if !runBankTest { s.T().Skip() diff --git a/tests/e2e/http_util.go b/tests/e2e/http_util.go index cbd2b2a10cc..593759ac8b7 100644 --- a/tests/e2e/http_util.go +++ b/tests/e2e/http_util.go @@ -1,6 +1,7 @@ package e2e import ( + "encoding/json" "fmt" "io" "net/http" @@ -20,3 +21,20 @@ func httpGet(endpoint string) ([]byte, error) { return body, nil } + +func readJSON(resp *http.Response) (map[string]interface{}, error) { + defer resp.Body.Close() + + body, readErr := io.ReadAll(resp.Body) + if readErr != nil { + return nil, fmt.Errorf("failed to read Body") + } + + var data map[string]interface{} + err := json.Unmarshal(body, &data) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal response body") + } + + return data, nil +}