Skip to content

Commit

Permalink
feat: x/auth determinism tests for Account query (cosmos#13255)
Browse files Browse the repository at this point in the history
* WIP: rapid tests

* remove commented code

* review changes

* review changes

* review changes

* review changes

* review changes

* review changes

* review changes

* review changes

* review changes

* review changes

* `go mod tidy`
  • Loading branch information
atheeshp authored and Wryhder committed Oct 26, 2022
1 parent 584ea19 commit ed0e61a
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 0 deletions.
1 change: 1 addition & 0 deletions simapp/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ require (
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
nhooyr.io/websocket v1.8.6 // indirect
pgregory.net/rapid v0.5.2 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

Expand Down
1 change: 1 addition & 0 deletions simapp/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1381,6 +1381,7 @@ nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k=
nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
pgregory.net/rapid v0.5.2 h1:zC+jmuzcz5yJvG/igG06aLx8kcGmZY435NcuyhblKjY=
pgregory.net/rapid v0.5.2/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
Expand Down
1 change: 1 addition & 0 deletions tests/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ require (
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
nhooyr.io/websocket v1.8.6 // indirect
pgregory.net/rapid v0.5.2 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

Expand Down
1 change: 1 addition & 0 deletions tests/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1383,6 +1383,7 @@ nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k=
nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
pgregory.net/rapid v0.5.2 h1:zC+jmuzcz5yJvG/igG06aLx8kcGmZY435NcuyhblKjY=
pgregory.net/rapid v0.5.2/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
Expand Down
9 changes: 9 additions & 0 deletions testutil/testdata/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"

"github.com/stretchr/testify/require"
"pgregory.net/rapid"

"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1"
Expand All @@ -12,6 +13,14 @@ import (
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)

// AddressGenerator creates and returns a random address generator using rapid.
func AddressGenerator(t *rapid.T) *rapid.Generator[sdk.AccAddress] {
return rapid.Custom(func(t *rapid.T) sdk.AccAddress {
pkBz := rapid.SliceOfN(rapid.Byte(), 20, 20).Draw(t, "hex")
return sdk.AccAddress(pkBz)
})
}

// KeyTestPubAddr generates a new secp256k1 keypair.
func KeyTestPubAddr() (cryptotypes.PrivKey, cryptotypes.PubKey, sdk.AccAddress) {
key := secp256k1.GenPrivKey()
Expand Down
120 changes: 120 additions & 0 deletions x/auth/keeper/deterministic_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package keeper_test

import (
"encoding/hex"
"testing"

"github.com/cosmos/cosmos-sdk/baseapp"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types"
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/auth/keeper"
"github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/stretchr/testify/suite"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"pgregory.net/rapid"
)

type DeterministicTestSuite struct {
suite.Suite

ctx sdk.Context
queryClient types.QueryClient
accountKeeper keeper.AccountKeeper
encCfg moduletestutil.TestEncodingConfig
}

func TestDeterministicTestSuite(t *testing.T) {
suite.Run(t, new(DeterministicTestSuite))
}

func (suite *DeterministicTestSuite) SetupTest() {
suite.encCfg = moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{})

key := sdk.NewKVStoreKey(types.StoreKey)
testCtx := testutil.DefaultContextWithDB(suite.T(), key, sdk.NewTransientStoreKey("transient_test"))
suite.ctx = testCtx.Ctx.WithBlockHeader(tmproto.Header{})

maccPerms := map[string][]string{
"fee_collector": nil,
"mint": {"minter"},
"bonded_tokens_pool": {"burner", "staking"},
"not_bonded_tokens_pool": {"burner", "staking"},
multiPerm: {"burner", "minter", "staking"},
randomPerm: {"random"},
}

suite.accountKeeper = keeper.NewAccountKeeper(
suite.encCfg.Codec,
key,
types.ProtoBaseAccount,
maccPerms,
"cosmos",
types.NewModuleAddress("gov").String(),
)

queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.encCfg.InterfaceRegistry)
types.RegisterQueryServer(queryHelper, suite.accountKeeper)
suite.queryClient = types.NewQueryClient(queryHelper)
}

func (suite *DeterministicTestSuite) runAccountIterations(addr sdk.AccAddress, prevRes types.AccountI) {
for i := 0; i < 1000; i++ {
acc, err := suite.queryClient.Account(suite.ctx, &types.QueryAccountRequest{Address: addr.String()})
suite.Require().NoError(err)
suite.Require().NotNil(acc)

var account types.AccountI
err = suite.encCfg.InterfaceRegistry.UnpackAny(acc.Account, &account)
suite.Require().NoError(err)
suite.Require().Equal(account.GetAddress(), addr)

if prevRes != nil {
any, err := codectypes.NewAnyWithValue(prevRes)
suite.Require().NoError(err)

suite.Require().Equal(acc.Account, any)
suite.Require().Equal(account, prevRes)
}

prevRes = account
}
}

func (suite *DeterministicTestSuite) TestGRPCQueryAccount() {
rapid.Check(suite.T(), func(t *rapid.T) {
pub := pubkeyGenerator(t).Draw(t, "pubkey")
addr := sdk.AccAddress(pub.Address())
accNum := rapid.Uint64().Draw(t, "account-number")
seq := rapid.Uint64().Draw(t, "sequence")

acc1 := types.NewBaseAccount(addr, &pub, accNum, seq)
suite.accountKeeper.SetAccount(suite.ctx, acc1)

suite.runAccountIterations(addr, acc1)
})

// Regression test
addr1 := sdk.MustAccAddressFromBech32("cosmos139f7kncmglres2nf3h4hc4tade85ekfr8sulz5")
pub, err := hex.DecodeString("02950e1cdfcb133d6024109fd489f734eeb4502418e538c28481f22bce276f248c")
suite.Require().NoError(err)

accNum := uint64(10087)
seq := uint64(0)

acc1 := types.NewBaseAccount(addr1, &secp256k1.PubKey{Key: pub}, accNum, seq)

suite.accountKeeper.SetAccount(suite.ctx, acc1)
suite.runAccountIterations(addr1, acc1)
}

// pubkeyGenerator creates and returns a random pubkey generator using rapid.
func pubkeyGenerator(t *rapid.T) *rapid.Generator[secp256k1.PubKey] {
return rapid.Custom(func(t *rapid.T) secp256k1.PubKey {
pkBz := rapid.SliceOfN(rapid.Byte(), 33, 33).Draw(t, "hex")
return secp256k1.PubKey{Key: pkBz}
})
}

0 comments on commit ed0e61a

Please sign in to comment.