From 4b181afa46cd0e7e862ab5c4a9f35042ce55f94a Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Wed, 5 Oct 2022 13:06:47 -0400 Subject: [PATCH] test(`mint`): `types` package (#57) * update params * init test * partial update * cover params * minter * genesis * Update x/mint/types/params_test.go Co-authored-by: Lucas Bertrand * fix * refactor minter validate test * refactor genesis test * refactor params test * refactor params test * refactor params test * refactor params test * add more test cases * make tests visual Co-authored-by: Lucas Bertrand --- x/mint/genesis.go | 9 +- x/mint/simulation/genesis.go | 7 +- x/mint/types/genesis.go | 8 +- x/mint/types/genesis_test.go | 42 ++++ x/mint/types/minter.go | 8 +- x/mint/types/minter_test.go | 56 ++++- x/mint/types/params.go | 113 +++------- x/mint/types/params_test.go | 421 +++++++++++++++++++++++++++++++++++ x/mint/types/types_test.go | 11 + 9 files changed, 572 insertions(+), 103 deletions(-) create mode 100644 x/mint/types/genesis_test.go create mode 100644 x/mint/types/params_test.go create mode 100644 x/mint/types/types_test.go diff --git a/x/mint/genesis.go b/x/mint/genesis.go index c32b414..bbc871e 100644 --- a/x/mint/genesis.go +++ b/x/mint/genesis.go @@ -16,7 +16,10 @@ func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, ak types.AccountKeeper, // ExportGenesis returns a GenesisState for a given context and keeper. func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) *types.GenesisState { - minter := keeper.GetMinter(ctx) - params := keeper.GetParams(ctx) - return types.NewGenesisState(minter, params) + genesis := types.DefaultGenesis() + + genesis.Minter = keeper.GetMinter(ctx) + genesis.Params = keeper.GetParams(ctx) + + return genesis } diff --git a/x/mint/simulation/genesis.go b/x/mint/simulation/genesis.go index 03652eb..7b539b8 100644 --- a/x/mint/simulation/genesis.go +++ b/x/mint/simulation/genesis.go @@ -141,12 +141,15 @@ func RandomizedGenState(simState *module.SimulationState) { blocksPerYear := uint64(60 * 60 * 8766 / 5) params := types.NewParams(mintDenom, inflationRateChange, inflationMax, inflationMin, goalBonded, blocksPerYear, distributionProportions, developmentFundRecipients) - mintGenesis := types.NewGenesisState(types.InitialMinter(inflation), params) + mintGenesis := types.GenesisState{ + Minter: types.InitialMinter(inflation), + Params: params, + } bz, err := json.MarshalIndent(&mintGenesis, "", " ") if err != nil { panic(err) } fmt.Printf("Selected randomly generated minting parameters:\n%s\n", bz) - simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(mintGenesis) + simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(&mintGenesis) } diff --git a/x/mint/types/genesis.go b/x/mint/types/genesis.go index 2e212d6..3450761 100644 --- a/x/mint/types/genesis.go +++ b/x/mint/types/genesis.go @@ -1,12 +1,6 @@ package types // NewGenesisState creates a new GenesisState object -func NewGenesisState(minter Minter, params Params) *GenesisState { - return &GenesisState{ - Minter: minter, - Params: params, - } -} // DefaultGenesis creates a default GenesisState object func DefaultGenesis() *GenesisState { @@ -23,5 +17,5 @@ func (gs GenesisState) Validate() error { return err } - return ValidateMinter(gs.Minter) + return gs.Minter.Validate() } diff --git a/x/mint/types/genesis_test.go b/x/mint/types/genesis_test.go new file mode 100644 index 0000000..8ab440c --- /dev/null +++ b/x/mint/types/genesis_test.go @@ -0,0 +1,42 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/ignite/modules/x/mint/types" +) + +func TestValidateGenesis(t *testing.T) { + invalid := types.DefaultGenesis() + // set inflation min to larger than inflation max + invalid.Params.InflationMin = invalid.Params.InflationMax.Add(invalid.Params.InflationMax) + + tests := []struct { + name string + genesis *types.GenesisState + isValid bool + }{ + { + name: "should validate valid genesis", + genesis: types.DefaultGenesis(), + isValid: true, + }, + { + name: "should prevent invalid params", + genesis: invalid, + isValid: false, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.genesis.Validate() + if !tc.isValid { + require.Error(t, err) + return + } + require.NoError(t, err) + }) + } +} diff --git a/x/mint/types/minter.go b/x/mint/types/minter.go index 0f0a4da..e9d2edb 100644 --- a/x/mint/types/minter.go +++ b/x/mint/types/minter.go @@ -32,11 +32,11 @@ func DefaultInitialMinter() Minter { ) } -// validate minter -func ValidateMinter(minter Minter) error { - if minter.Inflation.IsNegative() { +// Validate checks if inflation parameter is negative +func (m Minter) Validate() error { + if m.Inflation.IsNegative() { return fmt.Errorf("mint parameter Inflation should be positive, is %s", - minter.Inflation.String()) + m.Inflation.String()) } return nil } diff --git a/x/mint/types/minter_test.go b/x/mint/types/minter_test.go index a394620..b2bc347 100644 --- a/x/mint/types/minter_test.go +++ b/x/mint/types/minter_test.go @@ -1,4 +1,4 @@ -package types +package types_test import ( "math/rand" @@ -7,11 +7,45 @@ import ( sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" + + "github.com/ignite/modules/x/mint/types" ) +func TestValidateMinter(t *testing.T) { + invalid := types.DefaultInitialMinter() + invalid.Inflation = sdk.NewDec(-1) + + tests := []struct { + name string + minter types.Minter + isValid bool + }{ + { + name: "should validate valid minter", + minter: types.DefaultInitialMinter(), + isValid: true, + }, + { + name: "should prevent validate for minter with negative inflation", + minter: invalid, + isValid: false, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.minter.Validate() + if !tc.isValid { + require.Error(t, err) + return + } + require.NoError(t, err) + }) + } +} + func TestNextInflation(t *testing.T) { - minter := DefaultInitialMinter() - params := DefaultParams() + minter := types.DefaultInitialMinter() + params := types.DefaultParams() blocksPerYr := sdk.NewDec(int64(params.BlocksPerYear)) // Governing Mechanism: @@ -59,8 +93,8 @@ func TestNextInflation(t *testing.T) { } func TestBlockProvision(t *testing.T) { - minter := InitialMinter(sdk.NewDecWithPrec(1, 1)) - params := DefaultParams() + minter := types.InitialMinter(sdk.NewDecWithPrec(1, 1)) + params := types.DefaultParams() secondsPerYear := int64(60 * 60 * 8766) @@ -94,8 +128,8 @@ func TestBlockProvision(t *testing.T) { // BenchmarkBlockProvision-4 3000000 429 ns/op func BenchmarkBlockProvision(b *testing.B) { b.ReportAllocs() - minter := InitialMinter(sdk.NewDecWithPrec(1, 1)) - params := DefaultParams() + minter := types.InitialMinter(sdk.NewDecWithPrec(1, 1)) + params := types.DefaultParams() s1 := rand.NewSource(100) r1 := rand.New(s1) @@ -111,8 +145,8 @@ func BenchmarkBlockProvision(b *testing.B) { // BenchmarkNextInflation-4 1000000 1828 ns/op func BenchmarkNextInflation(b *testing.B) { b.ReportAllocs() - minter := InitialMinter(sdk.NewDecWithPrec(1, 1)) - params := DefaultParams() + minter := types.InitialMinter(sdk.NewDecWithPrec(1, 1)) + params := types.DefaultParams() bondedRatio := sdk.NewDecWithPrec(1, 1) // run the NextInflationRate function b.N times @@ -125,8 +159,8 @@ func BenchmarkNextInflation(b *testing.B) { // BenchmarkNextAnnualProvisions-4 5000000 251 ns/op func BenchmarkNextAnnualProvisions(b *testing.B) { b.ReportAllocs() - minter := InitialMinter(sdk.NewDecWithPrec(1, 1)) - params := DefaultParams() + minter := types.InitialMinter(sdk.NewDecWithPrec(1, 1)) + params := types.DefaultParams() totalSupply := sdkmath.NewInt(100000000000000) // run the NextAnnualProvisions function b.N times diff --git a/x/mint/types/params.go b/x/mint/types/params.go index 5f1ba12..a78eb12 100644 --- a/x/mint/types/params.go +++ b/x/mint/types/params.go @@ -21,6 +21,19 @@ var ( KeyBlocksPerYear = []byte("BlocksPerYear") KeyDistributionProportions = []byte("DistributionProportions") KeyFundedAddresses = []byte("FundedAddresses") + + DefaultMintDenom = sdk.DefaultBondDenom + DefaultInflationRateChange = sdk.NewDecWithPrec(13, 2) + DefaultInflationMax = sdk.NewDecWithPrec(20, 2) + DefaultInflationMin = sdk.NewDecWithPrec(7, 2) + DefaultGoalBonded = sdk.NewDecWithPrec(67, 2) + DefaultBlocksPerYear = uint64(60 * 60 * 8766 / 5) // assuming 5 seconds block times + DefaultDistributionProportions = DistributionProportions{ + Staking: sdk.NewDecWithPrec(3, 1), // 0.3 + FundedAddresses: sdk.NewDecWithPrec(4, 1), // 0.4 + CommunityPool: sdk.NewDecWithPrec(3, 1), // 0.3 + } + DefaultFundedAddresses []WeightedAddress ) // ParamTable for minting module. @@ -50,39 +63,35 @@ func NewParams( } } -// default minting module parameters +// DefaultParams returns default minting module parameters func DefaultParams() Params { - return Params{ - MintDenom: sdk.DefaultBondDenom, - InflationRateChange: sdk.NewDecWithPrec(13, 2), - InflationMax: sdk.NewDecWithPrec(20, 2), - InflationMin: sdk.NewDecWithPrec(7, 2), - GoalBonded: sdk.NewDecWithPrec(67, 2), - BlocksPerYear: uint64(60 * 60 * 8766 / 5), // assuming 5 seconds block times - DistributionProportions: DistributionProportions{ - Staking: sdk.NewDecWithPrec(3, 1), // 0.3 - FundedAddresses: sdk.NewDecWithPrec(4, 1), // 0.4 - CommunityPool: sdk.NewDecWithPrec(3, 1), // 0.3 - }, - FundedAddresses: []WeightedAddress{}, - } + return NewParams( + DefaultMintDenom, + DefaultInflationRateChange, + DefaultInflationMax, + DefaultInflationMin, + DefaultGoalBonded, + DefaultBlocksPerYear, + DefaultDistributionProportions, + DefaultFundedAddresses, + ) } -// validate params +// Validate validates all params func (p Params) Validate() error { if err := validateMintDenom(p.MintDenom); err != nil { return err } - if err := validateInflationRateChange(p.InflationRateChange); err != nil { + if err := validateDec(p.InflationRateChange); err != nil { return err } - if err := validateInflationMax(p.InflationMax); err != nil { + if err := validateDec(p.InflationMax); err != nil { return err } - if err := validateInflationMin(p.InflationMin); err != nil { + if err := validateDec(p.InflationMin); err != nil { return err } - if err := validateGoalBonded(p.GoalBonded); err != nil { + if err := validateDec(p.GoalBonded); err != nil { return err } if err := validateBlocksPerYear(p.BlocksPerYear); err != nil { @@ -106,14 +115,14 @@ func (p Params) String() string { return string(out) } -// Implements params.ParamSet +// ParamSetPairs implements params.ParamSet func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { return paramtypes.ParamSetPairs{ paramtypes.NewParamSetPair(KeyMintDenom, &p.MintDenom, validateMintDenom), - paramtypes.NewParamSetPair(KeyInflationRateChange, &p.InflationRateChange, validateInflationRateChange), - paramtypes.NewParamSetPair(KeyInflationMax, &p.InflationMax, validateInflationMax), - paramtypes.NewParamSetPair(KeyInflationMin, &p.InflationMin, validateInflationMin), - paramtypes.NewParamSetPair(KeyGoalBonded, &p.GoalBonded, validateGoalBonded), + paramtypes.NewParamSetPair(KeyInflationRateChange, &p.InflationRateChange, validateDec), + paramtypes.NewParamSetPair(KeyInflationMax, &p.InflationMax, validateDec), + paramtypes.NewParamSetPair(KeyInflationMin, &p.InflationMin, validateDec), + paramtypes.NewParamSetPair(KeyGoalBonded, &p.GoalBonded, validateDec), paramtypes.NewParamSetPair(KeyBlocksPerYear, &p.BlocksPerYear, validateBlocksPerYear), paramtypes.NewParamSetPair(KeyDistributionProportions, &p.DistributionProportions, validateDistributionProportions), paramtypes.NewParamSetPair(KeyFundedAddresses, &p.FundedAddresses, validateWeightedAddresses), @@ -136,65 +145,17 @@ func validateMintDenom(i interface{}) error { return nil } -func validateInflationRateChange(i interface{}) error { - v, ok := i.(sdk.Dec) - if !ok { - return fmt.Errorf("invalid parameter type: %T", i) - } - - if v.IsNegative() { - return fmt.Errorf("inflation rate change cannot be negative: %s", v) - } - if v.GT(sdk.OneDec()) { - return fmt.Errorf("inflation rate change too large: %s", v) - } - - return nil -} - -func validateInflationMax(i interface{}) error { - v, ok := i.(sdk.Dec) - if !ok { - return fmt.Errorf("invalid parameter type: %T", i) - } - - if v.IsNegative() { - return fmt.Errorf("max inflation cannot be negative: %s", v) - } - if v.GT(sdk.OneDec()) { - return fmt.Errorf("max inflation too large: %s", v) - } - - return nil -} - -func validateInflationMin(i interface{}) error { - v, ok := i.(sdk.Dec) - if !ok { - return fmt.Errorf("invalid parameter type: %T", i) - } - - if v.IsNegative() { - return fmt.Errorf("min inflation cannot be negative: %s", v) - } - if v.GT(sdk.OneDec()) { - return fmt.Errorf("min inflation too large: %s", v) - } - - return nil -} - -func validateGoalBonded(i interface{}) error { +func validateDec(i interface{}) error { v, ok := i.(sdk.Dec) if !ok { return fmt.Errorf("invalid parameter type: %T", i) } if v.IsNegative() { - return fmt.Errorf("goal bonded cannot be negative: %s", v) + return fmt.Errorf("cannot be negative: %s", v) } if v.GT(sdk.OneDec()) { - return fmt.Errorf("goal bonded too large: %s", v) + return fmt.Errorf("dec too large: %s", v) } return nil diff --git a/x/mint/types/params_test.go b/x/mint/types/params_test.go new file mode 100644 index 0000000..17a2935 --- /dev/null +++ b/x/mint/types/params_test.go @@ -0,0 +1,421 @@ +package types + +import ( + "github.com/ignite/modules/testutil/sample" + "math/rand" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func TestParamsValidate(t *testing.T) { + tests := []struct { + name string + params Params + isValid bool + }{ + { + name: "should validate valid params", + params: DefaultParams(), + isValid: true, + }, + { + name: "should prevent validate params with inflation max less than inflation min", + params: Params{ + MintDenom: DefaultMintDenom, + InflationRateChange: DefaultInflationRateChange, + InflationMax: DefaultInflationMax, + InflationMin: DefaultInflationMin.Add(DefaultInflationMax), + GoalBonded: DefaultGoalBonded, + BlocksPerYear: DefaultBlocksPerYear, + DistributionProportions: DefaultDistributionProportions, + FundedAddresses: DefaultFundedAddresses, + }, + isValid: false, + }, + { + name: "should prevent validate params with negative inflation min", + params: Params{ + MintDenom: DefaultMintDenom, + InflationRateChange: DefaultInflationRateChange, + InflationMax: DefaultInflationMax, + InflationMin: sdk.NewDec(-1), + GoalBonded: DefaultGoalBonded, + BlocksPerYear: DefaultBlocksPerYear, + DistributionProportions: DefaultDistributionProportions, + FundedAddresses: DefaultFundedAddresses, + }, + isValid: false, + }, + { + name: "should prevent validate params with negative inflation max", + params: Params{ + MintDenom: DefaultMintDenom, + InflationRateChange: DefaultInflationRateChange, + InflationMax: sdk.NewDec(-1), + InflationMin: DefaultInflationMin, + GoalBonded: DefaultGoalBonded, + BlocksPerYear: DefaultBlocksPerYear, + DistributionProportions: DefaultDistributionProportions, + FundedAddresses: DefaultFundedAddresses, + }, + isValid: false, + }, + { + name: "should prevent validate params with negative goal bonded", + params: Params{ + MintDenom: DefaultMintDenom, + InflationRateChange: DefaultInflationRateChange, + InflationMax: DefaultInflationMax, + InflationMin: DefaultInflationMin, + GoalBonded: sdk.NewDec(-1), + BlocksPerYear: DefaultBlocksPerYear, + DistributionProportions: DefaultDistributionProportions, + FundedAddresses: DefaultFundedAddresses, + }, + isValid: false, + }, + { + name: "should prevent invalid mint denom", + params: Params{ + MintDenom: "", + InflationRateChange: DefaultInflationRateChange, + InflationMax: DefaultInflationMax, + InflationMin: DefaultInflationMin, + GoalBonded: DefaultGoalBonded, + BlocksPerYear: DefaultBlocksPerYear, + DistributionProportions: DefaultDistributionProportions, + FundedAddresses: DefaultFundedAddresses, + }, + isValid: false, + }, + { + name: "should prevent invalid blocks per year", + params: Params{ + MintDenom: DefaultMintDenom, + InflationRateChange: DefaultInflationRateChange, + InflationMax: DefaultInflationMax, + InflationMin: DefaultInflationMin, + GoalBonded: DefaultGoalBonded, + BlocksPerYear: 0, + DistributionProportions: DefaultDistributionProportions, + FundedAddresses: DefaultFundedAddresses, + }, + isValid: false, + }, + { + name: "should prevent invalid distribution proportions", + params: Params{ + MintDenom: DefaultMintDenom, + InflationRateChange: DefaultInflationRateChange, + InflationMax: DefaultInflationMax, + InflationMin: DefaultInflationMin, + GoalBonded: DefaultGoalBonded, + BlocksPerYear: DefaultBlocksPerYear, + DistributionProportions: DistributionProportions{ + Staking: sdk.NewDecWithPrec(3, 1), // 0.3 + FundedAddresses: sdk.NewDecWithPrec(-4, 1), // -0.4 + CommunityPool: sdk.NewDecWithPrec(3, 1), // 0.3 + }, + FundedAddresses: DefaultFundedAddresses, + }, + isValid: false, + }, + { + name: "should prevent invalid weighted addresses", + params: Params{ + MintDenom: DefaultMintDenom, + InflationRateChange: DefaultInflationRateChange, + InflationMax: DefaultInflationMax, + InflationMin: DefaultInflationMin, + GoalBonded: DefaultGoalBonded, + BlocksPerYear: DefaultBlocksPerYear, + DistributionProportions: DefaultDistributionProportions, + FundedAddresses: []WeightedAddress{ + { + Address: "invalid", + Weight: sdk.OneDec(), + }, + }, + }, + isValid: false, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.params.Validate() + if !tc.isValid { + require.Error(t, err) + return + } + require.NoError(t, err) + }) + } +} + +func TestValidateMintDenom(t *testing.T) { + tests := []struct { + name string + denom interface{} + isValid bool + }{ + { + name: "should validate valid mint denom", + denom: DefaultMintDenom, + isValid: true, + }, + { + name: "should prevent validate mint denom with invalid interface", + denom: 10, + isValid: false, + }, + { + name: "should prevent validate empty mint denom", + denom: "", + isValid: false, + }, + { + name: "should prevent validate mint denom with invalid value", + denom: "invalid&", + isValid: false, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := validateMintDenom(tc.denom) + if !tc.isValid { + require.Error(t, err) + return + } + require.NoError(t, err) + }) + } +} + +func TestValidateDec(t *testing.T) { + tests := []struct { + name string + value interface{} + isValid bool + }{ + { + name: "should validate valid dec", + value: DefaultInflationRateChange, + isValid: true, + }, + { + name: "should prevent validate dec with invalid interface", + value: "string", + isValid: false, + }, + { + name: "should prevent validate dec with negative value", + value: sdk.NewDec(-1), + isValid: false, + }, { + name: "should prevent validate dec too large a value", + value: sdk.NewDec(2), + isValid: false, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := validateDec(tc.value) + if !tc.isValid { + require.Error(t, err) + return + } + require.NoError(t, err) + }) + } +} + +func TestValidateBlocksPerYear(t *testing.T) { + tests := []struct { + name string + value interface{} + isValid bool + }{ + { + name: "should validate valid blocks per year", + value: DefaultBlocksPerYear, + isValid: true, + }, + { + name: "should prevent validate blocks per year with invalid interface", + value: "string", + isValid: false, + }, + { + name: "should prevent validate blocks per year with zero value", + value: uint64(0), + isValid: false, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := validateBlocksPerYear(tc.value) + if !tc.isValid { + require.Error(t, err) + return + } + require.NoError(t, err) + }) + } +} + +func TestValidateDistributionProportions(t *testing.T) { + tests := []struct { + name string + distrProportions interface{} + isValid bool + }{ + { + name: "should validate valid distribution proportions", + distrProportions: DefaultDistributionProportions, + isValid: true, + }, + { + name: "should prevent validate distribution proportions with invalid interface", + distrProportions: "string", + isValid: false, + }, + { + name: "should prevent validate distribution proportions with negative staking ratio", + distrProportions: DistributionProportions{ + Staking: sdk.NewDecWithPrec(-3, 1), // -0.3 + FundedAddresses: sdk.NewDecWithPrec(4, 1), // 0.4 + CommunityPool: sdk.NewDecWithPrec(3, 1), // 0.3 + }, + isValid: false, + }, + { + name: "should prevent validate distribution proportions with negative funded addresses ratio", + distrProportions: DistributionProportions{ + Staking: sdk.NewDecWithPrec(3, 1), // 0.3 + FundedAddresses: sdk.NewDecWithPrec(-4, 1), // -0.4 + CommunityPool: sdk.NewDecWithPrec(3, 1), // 0.3 + }, + isValid: false, + }, + { + name: "should prevent validate distribution proportions with negative community pool ratio", + distrProportions: DistributionProportions{ + Staking: sdk.NewDecWithPrec(3, 1), // 0.3 + FundedAddresses: sdk.NewDecWithPrec(4, 1), // 0.4 + CommunityPool: sdk.NewDecWithPrec(-3, 1), // -0.3 + }, + isValid: false, + }, + { + name: "should prevent validate distribution proportions total ratio not equal to 1", + distrProportions: DistributionProportions{ + Staking: sdk.NewDecWithPrec(3, 1), // 0.3 + FundedAddresses: sdk.NewDecWithPrec(4, 1), // 0.4 + CommunityPool: sdk.NewDecWithPrec(31, 2), // 0.31 + }, + isValid: false, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := validateDistributionProportions(tc.distrProportions) + if !tc.isValid { + require.Error(t, err) + return + } + require.NoError(t, err) + }) + } +} + +func TestValidateWeightedAddresses(t *testing.T) { + s := rand.NewSource(1) + r := rand.New(s) + + tests := []struct { + name string + weightedAddresses interface{} + isValid bool + }{ + { + name: "should validate valid weighted addresses", + weightedAddresses: []WeightedAddress{ + { + Address: sample.Address(r), + Weight: sdk.NewDecWithPrec(5, 1), + }, + { + Address: sample.Address(r), + Weight: sdk.NewDecWithPrec(5, 1), + }, + }, + isValid: true, + }, + { + name: "should validate valid empty weighted addresses", + weightedAddresses: DefaultFundedAddresses, + isValid: true, + }, + { + name: "should prevent validate weighed addresses with invalid interface", + weightedAddresses: "string", + isValid: false, + }, + { + name: "should prevent validate weighed addresses with invalid SDK address", + weightedAddresses: []WeightedAddress{ + { + Address: "invalid", + Weight: sdk.OneDec(), + }, + }, + isValid: false, + }, + { + name: "should prevent validate weighed addresses with negative value", + weightedAddresses: []WeightedAddress{ + { + Address: sample.Address(r), + Weight: sdk.NewDec(-1), + }, + }, + isValid: false, + }, + { + name: "should prevent validate weighed addresses with weight greater than 1", + weightedAddresses: []WeightedAddress{ + { + Address: sample.Address(r), + Weight: sdk.NewDec(2), + }, + }, + isValid: false, + }, + { + name: "should prevent validate weighed addresses with sum greater than 1", + weightedAddresses: []WeightedAddress{ + { + Address: sample.Address(r), + Weight: sdk.NewDecWithPrec(6, 1), + }, + { + Address: sample.Address(r), + Weight: sdk.NewDecWithPrec(5, 1), + }, + }, + isValid: false, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := validateWeightedAddresses(tc.weightedAddresses) + if !tc.isValid { + require.Error(t, err) + return + } + require.NoError(t, err) + }) + } +} diff --git a/x/mint/types/types_test.go b/x/mint/types/types_test.go new file mode 100644 index 0000000..a796ba8 --- /dev/null +++ b/x/mint/types/types_test.go @@ -0,0 +1,11 @@ +package types_test + +import "math/rand" + +var r *rand.Rand + +// initialize random generator +func init() { + s := rand.NewSource(1) + r = rand.New(s) +}