-
Notifications
You must be signed in to change notification settings - Fork 270
test(grpc-suite): add post-upgrade gRPC surface coverage #2075
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
Open
chalabi2
wants to merge
15
commits into
main
Choose a base branch
from
feat/post-upgrade-grpc-suite
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
8573a9f
test(upgrade): add exhaustive post-upgrade gRPC tx/query suite
chalabi2 73463eb
test(upgrade): add market, audit and escrow gRPC packs
chalabi2 eaaec84
test(upgrade): add cert gRPC pack (create + revoke)
chalabi2 665b862
test(upgrade): add oracle gRPC pack (authorize source + add price)
chalabi2 87494a0
test(upgrade): add bme pack and enforce full Akash coverage
chalabi2 97bc6d2
docs(upgrade): describe grpcsuite scope as the live main surface
chalabi2 c8a98f9
test(upgrade): add negative cases and deep query assertions per Akash…
chalabi2 4310812
fix(upgrade): own deployments from the funder to avoid uact transfers
chalabi2 aa5373f
test(upgrade): gate the gRPC suite behind an opt-in -grpc-suite flag
chalabi2 7d5a20b
fix(grpc-suite): handle real fork tx inclusion
chalabi2 1d5beb8
test(grpc-suite): cover cosmos sdk surface post-upgrade
chalabi2 7bad6ff
test(grpc-suite): add split surface test targets
chalabi2 496e970
fix(grpc-suite): address review robustness issues
chalabi2 5fcf4eb
fix(grpc-suite): address nitpick assertions
chalabi2 32af38d
test(grpc-suite): cover cosmwasm transactions
chalabi2 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| //go:build e2e.integration | ||
|
|
||
| // Package fullsurface hosts the in-process driver for the exhaustive gRPC | ||
| // transaction/query suite (grpcsuite). It spins up a single-validator | ||
| // testutil/network and runs the same suite that the post-upgrade worker runs | ||
| // against a testnetify-forked node, giving a fast (minutes) iteration and per-PR | ||
| // CI signal without the full upgrade cycle. | ||
| // | ||
| // It lives in its own package (not tests/e2e) so it compiles standalone against | ||
| // the pinned SDK; the existing tests/e2e integration tests currently only build | ||
| // against the workspace-local chain-sdk. | ||
| package fullsurface | ||
|
|
||
| import ( | ||
| "context" | ||
| "encoding/json" | ||
| "flag" | ||
| "path/filepath" | ||
| "testing" | ||
| "time" | ||
|
|
||
| "github.com/stretchr/testify/require" | ||
|
|
||
| "github.com/cosmos/cosmos-sdk/codec" | ||
| sdk "github.com/cosmos/cosmos-sdk/types" | ||
| govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" | ||
| govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" | ||
|
|
||
| "pkg.akt.dev/node/v2/tests/upgrade/grpcsuite" | ||
| "pkg.akt.dev/node/v2/testutil" | ||
| "pkg.akt.dev/node/v2/testutil/network" | ||
| ) | ||
|
|
||
| var grpcSuiteMode = flag.String("grpc-suite-mode", string(grpcsuite.RunModeAll), "grpcsuite run mode: all, tx, or query") | ||
|
|
||
| func TestFullSurfaceGRPC(t *testing.T) { | ||
| mode, err := grpcsuite.ParseRunMode(*grpcSuiteMode) | ||
| require.NoError(t, err) | ||
|
|
||
| // Short gov voting period + low min deposit so the suite's gov fast-path (used | ||
| // for every MsgUpdateParams and other gov-gated messages) completes quickly. | ||
| // The post-upgrade harness gets the equivalent via tests/upgrade/testnet.json. | ||
| cfg := network.DefaultConfig(testutil.NewTestNetworkFixture, | ||
| network.WithInterceptState(func(cdc codec.Codec, moduleName string, state json.RawMessage) json.RawMessage { | ||
| if moduleName != govtypes.ModuleName { | ||
| return nil | ||
| } | ||
| var gs govv1.GenesisState | ||
| cdc.MustUnmarshalJSON(state, &gs) | ||
| vp := 8 * time.Second | ||
| ep := 6 * time.Second | ||
| gs.Params.VotingPeriod = &vp | ||
| gs.Params.ExpeditedVotingPeriod = &ep | ||
| gs.Params.MinDeposit = sdk.NewCoins(sdk.NewInt64Coin("uakt", 10_000_000)) | ||
| return cdc.MustMarshalJSON(&gs) | ||
| }), | ||
| ) | ||
| cfg.NumValidators = 1 | ||
|
|
||
| net := network.New(t, cfg) | ||
| defer net.Cleanup() | ||
|
|
||
| _, err = net.WaitForHeightWithTimeout(2, 30*time.Second) | ||
| require.NoError(t, err) | ||
|
|
||
| val := net.Validators[0] | ||
| require.NotEmpty(t, val.AppConfig.GRPC.Address, "gRPC server must be enabled") | ||
|
|
||
| root, err := filepath.Abs("../..") | ||
| require.NoError(t, err) | ||
|
|
||
| env := grpcsuite.Env{ | ||
| GRPCEndpoint: val.AppConfig.GRPC.Address, | ||
| ChainID: cfg.ChainID, | ||
| RepoRoot: root, | ||
| Cdc: cfg.Codec, | ||
| InterfaceReg: cfg.InterfaceRegistry, | ||
| TxConfig: cfg.TxConfig, | ||
| Amino: cfg.LegacyAmino, | ||
| Keyring: val.ClientCtx.Keyring, | ||
| Funder: "node0", // validator key name in the keyring | ||
| FunderAddr: val.Address, | ||
| BondDenom: cfg.BondDenom, | ||
| GasPrices: "0.025uakt", | ||
| // Enforce full coverage: fail if any in-scope tx or query is not | ||
| // exercised (a new RPC added by a future upgrade turns this red). | ||
| RequireFullCoverage: true, | ||
| Mode: mode, | ||
| } | ||
|
|
||
| grpcsuite.Run(context.Background(), t, env) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| # grpcsuite — exhaustive post-upgrade gRPC tx/query verification | ||
|
|
||
| `grpcsuite` exercises **every in-scope Akash and mounted Cosmos SDK transaction, | ||
| plus every in-scope query over the chain's gRPC API** after a network upgrade, so | ||
| that a passing run means the upgraded chain's API surface is verified accurate. | ||
| CLI is explicitly out of scope. | ||
|
|
||
| It runs in two places against the **same** code: | ||
|
|
||
| | Driver | Build tag | Target | Speed | Purpose | | ||
| | --- | --- | --- | --- | --- | | ||
| | `tests/upgrade` universal worker (`grpcsurface_worker_test.go`) | `e2e.upgrade` | testnetify-forked, freshly-upgraded validator | slow (full upgrade) | **acceptance path** — runs after every upgrade | | ||
| | `tests/fullsurface` (`fullsurface_test.go`) | `e2e.integration` | in-process single-validator `testutil/network` | minutes | fast local iteration + per-PR CI | | ||
|
|
||
| Run the fast path: `make test-grpc-surface`. | ||
|
|
||
| For narrower local debugging: | ||
| - `make test-grpc-surface-tx` runs the authored tx packs and gates tx coverage. | ||
| Packs still call query RPCs for setup and assertions. | ||
| - `make test-grpc-surface-query` runs the dynamic query smoke sweep and gates | ||
| query coverage without mutating chain state. | ||
|
|
||
| The acceptance path runs automatically inside `make -C tests/upgrade test` (the | ||
| existing `network-upgrade` CI job), because the suite is registered as the | ||
| **universal post-upgrade worker** (runs for every upgrade name). | ||
|
|
||
| ## How it works | ||
|
|
||
| - **All checks run over gRPC.** Queries route through a gRPC-backed | ||
| `client.Context` (`WithGRPCClient`); transactions are signed locally and | ||
| broadcast via the cosmos `tx.ServiceClient`, then polled for inclusion — nothing | ||
| touches Comet RPC. See `grpcconn.go`, `txbroadcast.go`. | ||
| - **Dynamic discovery + coverage gate (`coverage.go`).** The binary drives *what* | ||
| is tested: gRPC server reflection lists the live Query services; the | ||
| InterfaceRegistry lists the registered `Msg` implementations, restricted to the | ||
| active served version. The gate fails if any in-scope Msg/query was never | ||
| exercised — so a new RPC added by a future upgrade turns CI red until a case | ||
| exists. This is what keeps "test every single one" self-maintaining. | ||
| - **Dynamic query smoke sweep (`smoke.go`).** Fires an empty request at every | ||
| discovered query method, auto-covering the entire query surface and failing on | ||
| any advertised-but-`Unimplemented` method. Authored query cases add correctness | ||
| with real inputs. | ||
| - **Authored, dependency-ordered packs (`pack_*.go`).** A valid tx needs real | ||
| prior state (lease ⇐ bid ⇐ order ⇐ deployment+provider), so transactions are | ||
| authored scenarios, not fuzzed. Packs run in order and thread created handles | ||
| through the shared `World`. | ||
| - **Governance fast-path (`gov.go`).** Gov-gated messages (every `MsgUpdateParams`, | ||
| `MsgFundVault`, etc.) are batched into one proposal, voted through by the | ||
| funder (who holds ~all voting power on a testnetify fork / single-validator | ||
| net), and recorded once passed. Requires a short voting period (set in | ||
| `tests/upgrade/testnet.json` and the in-process driver). | ||
|
|
||
| ## Adding a module pack | ||
|
|
||
| 1. Create `pack_<module>.go` implementing `Pack` (`Name`, `Available`, `Run`). | ||
| 2. Gate `Available` on `d.HasModule("akash.<module>.<version>")` (Query service). | ||
| 3. In `Run`, fund accounts via `s.FundAccountDefault`, build msgs with the SDK | ||
| types, broadcast with `s.BroadcastOK` (happy path) or `s.BroadcastExpectErr` | ||
| (negative / disabled), query with the generated `NewQueryClient(s.Conn)`. | ||
| 4. For gov-gated msgs, build them with `Authority: s.GovAuthority()` and pass via | ||
| `s.PassGovProposal(...)`. | ||
| 5. Publish handles other packs need via `s.World.Set`; read with `s.World.Get`. | ||
| 6. Register the pack in `pack.go` in dependency order. | ||
|
|
||
| The deployment, provider and gov-params packs are worked examples. | ||
|
|
||
| ## Status | ||
|
|
||
| **Full in-scope coverage** — run `make test-grpc-surface` and read the | ||
| `coverage:` line: | ||
| - **Queries: 130/130 in-scope methods** (smoke sweep + authored typed cases). | ||
| - **Transactions: 93/93 in-scope messages.** Akash coverage includes deployment, | ||
| provider, market, audit, escrow, cert, oracle, bme and module params. Cosmos SDK | ||
| coverage includes auth, authz, bank, consensus, distribution, evidence, | ||
| feegrant, gov v1, legacy gov v1beta1, mint, slashing, staking, upgrade and | ||
| vesting. CosmWasm coverage includes store, instantiate, execute, migrate, admin, | ||
| code config, pin/unpin and wasm params. | ||
|
|
||
| `RequireFullCoverage` is `true` in both drivers, so the gate **fails** if any | ||
| in-scope tx or query stops being exercised — e.g. when a future upgrade adds a new | ||
| Akash or mounted Cosmos SDK RPC, until a case is authored for it. | ||
|
|
||
| The suite targets exactly the surface the running `main` binary serves: discovery | ||
| is driven by gRPC reflection + the interface registry, and every pack is | ||
| reflection-gated (`Available`/`HasModule`). A pack whose module is not served by | ||
| the binary under test is skipped automatically, so the suite always matches the | ||
| active surface with no manual bookkeeping. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.