Skip to content

Commit

Permalink
feat(tests): add operators simulation tests
Browse files Browse the repository at this point in the history
  • Loading branch information
RiccardoM committed Nov 22, 2024
1 parent 5897c25 commit ee755c9
Show file tree
Hide file tree
Showing 12 changed files with 750 additions and 31 deletions.
3 changes: 2 additions & 1 deletion app/modules.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func appModules(

// MilkyWay modules
services.NewAppModule(appCodec, app.ServicesKeeper, app.AccountKeeper, app.BankKeeper),
operators.NewAppModule(appCodec, app.OperatorsKeeper),
operators.NewAppModule(appCodec, app.OperatorsKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
pools.NewAppModule(appCodec, app.PoolsKeeper),
restaking.NewAppModule(appCodec, app.RestakingKeeper),
assets.NewAppModule(appCodec, app.AssetsKeeper),
Expand Down Expand Up @@ -232,6 +232,7 @@ func simulationModules(

// MilkyWay modules
services.NewAppModule(appCodec, app.ServicesKeeper, app.AccountKeeper, app.BankKeeper),
operators.NewAppModule(appCodec, app.OperatorsKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
}
}

Expand Down
37 changes: 36 additions & 1 deletion testutils/simtesting/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package simtesting

import (
"math/rand"
"time"

sdkmath "cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
Expand All @@ -17,7 +19,11 @@ import (

// SendMsg sends a transaction with the specified message.
func SendMsg(
r *rand.Rand, moduleName string, app *baseapp.BaseApp, ak authkeeper.AccountKeeper, bk bankkeeper.Keeper,
r *rand.Rand,
moduleName string,
app *baseapp.BaseApp,
ak authkeeper.AccountKeeper,
bk bankkeeper.Keeper,
msg sdk.Msg, ctx sdk.Context,
simAccount simtypes.Account,
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
Expand Down Expand Up @@ -61,3 +67,32 @@ func GetSimAccount(address sdk.Address, accs []simtypes.Account) (simtypes.Accou
}
return simtypes.Account{}, false
}

// --------------------------------------------------------------------------------------------------------------------

// RandomString returns a random string of the specified size
func RandomString(r *rand.Rand, size int) string {
b := make([]byte, size)
for i := range b {
b[i] = byte(r.Intn(256))
}
return string(b)
}

// RandomFutureTime returns a random future time
func RandomFutureTime(r *rand.Rand, currentTime time.Time) time.Time {
return currentTime.Add(time.Duration(r.Int63n(1e9)))
}

// RandomDuration returns a random duration between the min and max
func RandomDuration(r *rand.Rand, min time.Duration, max time.Duration) time.Duration {
return time.Duration(r.Int63n(int64(max-min))) + min
}

// RandomCoin returns a random coin having the specified denomination and the max given amount
func RandomCoin(r *rand.Rand, denom string, maxAmount int) sdk.Coin {
return sdk.NewCoin(
denom,
sdkmath.NewInt(int64(r.Intn(maxAmount*1e6))),
)
}
2 changes: 1 addition & 1 deletion x/operators/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func GetCmdSetOperatorParams() *cobra.Command {
creator := clientCtx.FromAddress.String()

// Create and validate the message
msg := types.NewMsgSetOperatorParams(creator, id, types.NewOperatorParams(commissionRete))
msg := types.NewMsgSetOperatorParams(id, types.NewOperatorParams(commissionRete), creator)
if err = msg.ValidateBasic(); err != nil {
return fmt.Errorf("message validation failed: %w", err)
}
Expand Down
4 changes: 2 additions & 2 deletions x/operators/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type Keeper struct {

accountKeeper types.AccountKeeper
poolKeeper types.CommunityPoolKeeper
schema collections.Schema
Schema collections.Schema

nextOperatorID collections.Sequence // Next operator ID
operators collections.Map[uint32, types.Operator] // operator ID -> operator
Expand Down Expand Up @@ -85,7 +85,7 @@ func NewKeeper(
if err != nil {
panic(err)
}
k.schema = schema
k.Schema = schema

return k
}
Expand Down
78 changes: 57 additions & 21 deletions x/operators/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,6 @@ func (suite *KeeperTestSuite) TestMsgServer_DeleteOperator() {
}

func (suite *KeeperTestSuite) TestMsgServer_SetOperatorParams() {
testOperatorId := uint32(2)
operatorAdmin := "cosmos167x6ehhple8gwz5ezy9x0464jltvdpzl6qfdt4"

testCases := []struct {
Expand All @@ -895,37 +894,85 @@ func (suite *KeeperTestSuite) TestMsgServer_SetOperatorParams() {
}{
{
name: "set invalid params fails",
store: func(ctx sdk.Context) {
// Register a test operator
err := suite.k.CreateOperator(ctx, types.NewOperator(
1,
types.OPERATOR_STATUS_ACTIVE,
"MilkyWay Operator",
"https://milkyway.com",
"https://milkyway.com/picture",
operatorAdmin,
))
suite.Require().NoError(err)
},
msg: types.NewMsgSetOperatorParams(
operatorAdmin,
testOperatorId,
1,
types.NewOperatorParams(sdkmath.LegacyNewDec(-1)),
operatorAdmin,
),
shouldErr: true,
},
{
name: "not admin can't set params",
store: func(ctx sdk.Context) {
// Register a test operator
err := suite.k.CreateOperator(ctx, types.NewOperator(
1,
types.OPERATOR_STATUS_ACTIVE,
"MilkyWay Operator",
"https://milkyway.com",
"https://milkyway.com/picture",
operatorAdmin,
))
suite.Require().NoError(err)
},
msg: types.NewMsgSetOperatorParams(
"cosmos1d03wa9qd8flfjtvldndw5csv94tvg5hzfcmcgn",
testOperatorId,
1,
types.NewOperatorParams(sdkmath.LegacyMustNewDecFromStr("0.2")),
"cosmos1d03wa9qd8flfjtvldndw5csv94tvg5hzfcmcgn",
),
shouldErr: true,
},
{
name: "set params for not existing operator fails",
store: func(ctx sdk.Context) {
// Register a test operator
err := suite.k.CreateOperator(ctx, types.NewOperator(
1,
types.OPERATOR_STATUS_ACTIVE,
"MilkyWay Operator",
"https://milkyway.com",
"https://milkyway.com/picture",
operatorAdmin,
))
suite.Require().NoError(err)
},
msg: types.NewMsgSetOperatorParams(
operatorAdmin,
3,
types.NewOperatorParams(sdkmath.LegacyMustNewDecFromStr("0.2")),
operatorAdmin,
),
shouldErr: true,
},
{
name: "set params works properly",
store: func(ctx sdk.Context) {
// Register a test operator
err := suite.k.CreateOperator(ctx, types.NewOperator(
1,
types.OPERATOR_STATUS_ACTIVE,
"MilkyWay Operator",
"https://milkyway.com",
"https://milkyway.com/picture",
operatorAdmin,
))
suite.Require().NoError(err)
},
msg: types.NewMsgSetOperatorParams(
operatorAdmin,
testOperatorId,
1,
types.NewOperatorParams(sdkmath.LegacyMustNewDecFromStr("0.2")),
operatorAdmin,
),
expEvents: []sdk.Event{
sdk.NewEvent(
Expand All @@ -934,7 +981,7 @@ func (suite *KeeperTestSuite) TestMsgServer_SetOperatorParams() {
},
shouldErr: false,
check: func(ctx sdk.Context) {
params, err := suite.k.GetOperatorParams(ctx, testOperatorId)
params, err := suite.k.GetOperatorParams(ctx, 1)
suite.Require().Nil(err)
suite.Require().Equal(types.NewOperatorParams(
sdkmath.LegacyMustNewDecFromStr("0.2"),
Expand All @@ -947,23 +994,12 @@ func (suite *KeeperTestSuite) TestMsgServer_SetOperatorParams() {
tc := tc
suite.Run(tc.name, func() {
suite.SetupTest()
ctx := suite.ctx

ctx, _ := suite.ctx.CacheContext()
if tc.store != nil {
tc.store(ctx)
}

// Register a test operator
err := suite.k.CreateOperator(ctx, types.NewOperator(
testOperatorId,
types.OPERATOR_STATUS_ACTIVE,
"MilkyWay Operator",
"https://milkyway.com",
"https://milkyway.com/picture",
operatorAdmin,
))
suite.Require().NoError(err)

msgServer := keeper.NewMsgServer(suite.k)
res, err := msgServer.SetOperatorParams(ctx, tc.msg)
if tc.shouldErr {
Expand Down
53 changes: 50 additions & 3 deletions x/operators/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import (
"fmt"

"cosmossdk.io/core/appmodule"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/spf13/cobra"

Expand All @@ -19,6 +23,7 @@ import (

"github.com/milkyway-labs/milkyway/x/operators/client/cli"
"github.com/milkyway-labs/milkyway/x/operators/keeper"
"github.com/milkyway-labs/milkyway/x/operators/simulation"
"github.com/milkyway-labs/milkyway/x/operators/types"
)

Expand Down Expand Up @@ -93,14 +98,27 @@ func (a AppModuleBasic) GetTxCmd() *cobra.Command {
type AppModule struct {
AppModuleBasic

// To ensure setting hooks properly, keeper must be a reference
keeper *keeper.Keeper
}

func NewAppModule(cdc codec.Codec, keeper *keeper.Keeper) AppModule {
// To ensure setting hooks properly, keeper must be a reference
accountKeeper authkeeper.AccountKeeper
bankKeeper bankkeeper.Keeper
stakingKeeper *stakingkeeper.Keeper
}

func NewAppModule(
cdc codec.Codec,
keeper *keeper.Keeper,
accountKeeper authkeeper.AccountKeeper,
bankKeeper bankkeeper.Keeper,
stakingKeeper *stakingkeeper.Keeper,
) AppModule {
return AppModule{
AppModuleBasic: NewAppModuleBasic(cdc),
keeper: keeper,
accountKeeper: accountKeeper,
bankKeeper: bankKeeper,
stakingKeeper: stakingKeeper,
}
}

Expand Down Expand Up @@ -150,3 +168,32 @@ func (am AppModule) BeginBlock(ctx context.Context) error {
func (am AppModule) IsOnePerModuleType() {}

func (am AppModule) IsAppModule() {}

// ----------------------------------------------------------------------------
// AppModuleSimulation
// ----------------------------------------------------------------------------

// GenerateGenesisState creates a randomized GenState of the services module.
func (AppModule) GenerateGenesisState(simState *module.SimulationState) {
simulation.RandomizedGenState(simState)
}

// ProposalMsgs returns msgs used for governance proposals for simulations.
func (am AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg {
return simulation.ProposalMsgs(am.stakingKeeper)
}

// RegisterStoreDecoder registers a decoder for services module's types.
func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {
sdr[types.StoreKey] = simulation.NewDecodeStore(am.keeper)
}

// WeightedOperations returns the all the services module operations with their respective weights.
func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation {
return simulation.WeightedOperations(
simState.AppParams,
am.accountKeeper,
am.bankKeeper,
am.keeper,
)
}
37 changes: 37 additions & 0 deletions x/operators/simulation/decoder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package simulation

import (
"bytes"
"fmt"

"github.com/cosmos/cosmos-sdk/types/kv"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"

"github.com/milkyway-labs/milkyway/x/operators/keeper"
"github.com/milkyway-labs/milkyway/x/operators/types"
)

// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's
// Value to the corresponding services type.
func NewDecodeStore(keeper *keeper.Keeper) func(kvA kv.Pair, kvB kv.Pair) string {
collectionsDecoder := simtypes.NewStoreDecoderFuncFromCollectionsSchema(keeper.Schema)

return func(kvA, kvB kv.Pair) string {
switch {
case bytes.Equal(kvA.Key[:1], types.ParamsKey),
bytes.Equal(kvA.Key[:1], types.NextOperatorIDKey),
bytes.Equal(kvA.Key[:1], types.OperatorPrefix),
bytes.Equal(kvA.Key[:1], types.OperatorAddressSetPrefix),
bytes.Equal(kvA.Key[:1], types.OperatorParamsMapPrefix):
return collectionsDecoder(kvA, kvB)

case bytes.Equal(kvA.Key[:1], types.InactivatingOperatorQueuePrefix):
valueA := types.GetOperatorIDFromBytes(kvA.Value)
valueB := types.GetOperatorIDFromBytes(kvB.Value)
return fmt.Sprintf("operatorIDA: %d\noperatorIDB: %d", valueA, valueB)

default:
panic(fmt.Sprintf("invalid services key prefix %X", kvA.Key[:1]))
}
}
}
Loading

0 comments on commit ee755c9

Please sign in to comment.