-
Notifications
You must be signed in to change notification settings - Fork 222
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
test(mstaking): implement StakeAuthorization tests #340
base: main
Are you sure you want to change the base?
Conversation
Implements comprehensive test suite for StakeAuthorization in the mstaking module. The tests cover: - Creation of new StakeAuthorization objects - Basic validation of authorization parameters - Message acceptance logic with allow/deny lists - Token limit validation and state updates - Message type URL handling for different authorization types This improves the overall test coverage and helps ensure the reliability of the staking authorization functionality.
📝 WalkthroughWalkthroughThe pull request introduces a comprehensive suite of unit tests for the Changes
Poem
Tip 🌐 Web search-backed reviews and chat
✨ Finishing Touches
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (3)
x/mstaking/types/authz_test.go (3)
15-75
: Add more test cases for comprehensive coverage.While the current test cases cover basic scenarios, consider adding the following cases to ensure thorough testing:
- Having both allow and deny lists (should error)
- Empty validator lists
- Nil amount
- Invalid authorization type
tests := []struct { name string allowedValidators []string deniedValidators []string authzType types.AuthorizationType amount sdk.Coins expectError bool }{ // ... existing test cases ... + { + name: "invalid - both allow and deny lists", + allowedValidators: []string{"val1"}, + deniedValidators: []string{"val2"}, + authzType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, + amount: sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(1000))), + expectError: true, + }, + { + name: "valid - empty validator lists", + allowedValidators: []string{}, + deniedValidators: nil, + authzType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, + amount: sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(1000))), + expectError: false, + }, + { + name: "valid - nil amount", + allowedValidators: []string{"val1"}, + deniedValidators: nil, + authzType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, + amount: nil, + expectError: false, + }, + { + name: "invalid - unspecified authorization type", + allowedValidators: []string{"val1"}, + deniedValidators: nil, + authzType: types.AuthorizationType_AUTHORIZATION_TYPE_UNSPECIFIED, + amount: sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(1000))), + expectError: true, + }, }
77-119
: Add test cases for additional validation scenarios.Consider adding the following test cases to improve validation coverage:
- Invalid coin denomination
- Zero amount coins
- Empty validator lists
tests := []struct { name string auth types.StakeAuthorization expectError bool }{ // ... existing test cases ... + { + name: "invalid - empty coin denomination", + auth: types.StakeAuthorization{ + MaxTokens: sdk.Coins{sdk.Coin{Denom: "", Amount: sdk.NewInt(1000)}}, + AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, + }, + expectError: true, + }, + { + name: "invalid - zero amount coins", + auth: types.StakeAuthorization{ + MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(0))), + AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, + }, + expectError: true, + }, + { + name: "valid - empty allow list", + auth: types.StakeAuthorization{ + Validators: &types.StakeAuthorization_AllowList{ + AllowList: &types.StakeAuthorization_Validators{ + Address: []string{}, + }, + }, + MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(1000))), + AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, + }, + expectError: false, + }, }
124-202
: Add test cases for additional message types.Consider adding test cases for:
- Redelegate message type
- Cancel unbonding delegation message type
- Invalid message type
tests := []struct { // ... existing struct fields ... }{ // ... existing test cases ... + { + name: "valid redelegate with allow list", + auth: types.StakeAuthorization{ + Validators: &types.StakeAuthorization_AllowList{ + AllowList: &types.StakeAuthorization_Validators{ + Address: []string{"val1"}, + }, + }, + MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(1000))), + AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE, + }, + msg: &types.MsgBeginRedelegate{ + DelegatorAddress: "delegator", + ValidatorSrcAddress: "val2", + ValidatorDstAddress: "val1", + Amount: sdk.NewCoin("stake", sdk.NewInt(500)), + }, + expectError: false, + }, + { + name: "valid cancel unbonding delegation", + auth: types.StakeAuthorization{ + Validators: &types.StakeAuthorization_AllowList{ + AllowList: &types.StakeAuthorization_Validators{ + Address: []string{"val1"}, + }, + }, + MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(1000))), + AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_CANCEL_UNBONDING_DELEGATION, + }, + msg: &types.MsgCancelUnbondingDelegation{ + DelegatorAddress: "delegator", + ValidatorAddress: "val1", + Amount: sdk.NewCoin("stake", sdk.NewInt(500)), + CreationHeight: 1, + }, + expectError: false, + }, + { + name: "invalid - wrong message type", + auth: types.StakeAuthorization{ + Validators: &types.StakeAuthorization_AllowList{ + AllowList: &types.StakeAuthorization_Validators{ + Address: []string{"val1"}, + }, + }, + MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", sdk.NewInt(1000))), + AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, + }, + msg: &types.MsgUndelegate{ + DelegatorAddress: "delegator", + ValidatorAddress: "val1", + Amount: sdk.NewCoin("stake", sdk.NewInt(500)), + }, + expectError: true, + }, }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
x/mstaking/types/authz_test.go
(1 hunks)
🔇 Additional comments (1)
x/mstaking/types/authz_test.go (1)
226-274
: LGTM!The test cases are comprehensive, covering all authorization types and properly verifying the panic case for unspecified type.
please use math.NewInt not sdk.NewInt |
@beer-1 corrected |
seems still failing, please run it on your local env first |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (2)
x/mstaking/types/authz_test.go (2)
78-120
: Enhance basic validation test coverage.Add test cases for:
- Nil MaxTokens
- Empty coins list
- Invalid coin denominations
Example test cases:
tests := []struct { // ... existing fields ... }{ // ... existing test cases ... + { + name: "invalid - nil max tokens", + auth: types.StakeAuthorization{ + MaxTokens: nil, + AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, + }, + expectError: true, + }, + { + name: "invalid - empty coins", + auth: types.StakeAuthorization{ + MaxTokens: sdk.Coins{}, + AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, + }, + expectError: true, + }, + { + name: "invalid - invalid denom", + auth: types.StakeAuthorization{ + MaxTokens: sdk.NewCoins(sdk.NewCoin("1invalid", math.NewInt(1000))), + AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, + }, + expectError: true, + }, }
225-273
: Improve error handling in MsgTypeURL tests.Consider:
- Using error return instead of panic in the
MsgTypeURL
method.- Adding test cases for invalid authorization type values.
Example improvement:
func (a StakeAuthorization) MsgTypeURL() string { - // Current implementation with panic + // Return error instead + if a.AuthorizationType == AuthorizationType_AUTHORIZATION_TYPE_UNSPECIFIED { + return "", fmt.Errorf("unspecified authorization type") + } // ... rest of the implementation } // In test: -if tc.expectError { - require.Panics(t, func() { auth.MsgTypeURL() }) - return -} +url, err := auth.MsgTypeURL() +if tc.expectError { + require.Error(t, err) + require.Empty(t, url) + return +}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
x/mstaking/types/authz_test.go
(1 hunks)
🔇 Additional comments (2)
x/mstaking/types/authz_test.go (2)
205-205
: Use proper context with block time and height.Replace empty context with proper test context.
-resp, err := tc.auth.Accept(context.Background(), tc.msg) +ctx := sdk.Context{}. + WithBlockTime(time.Now()). + WithBlockHeight(1). + WithGasMeter(sdk.NewInfiniteGasMeter()) +resp, err := tc.auth.Accept(ctx, tc.msg)
1-274
: Verify test coverage for StakeAuthorization implementation.Let's verify the test coverage for the StakeAuthorization implementation.
✅ Verification successful
Let's gather more details about the StakeAuthorization implementation. We'll search for the definition of both
NewStakeAuthorization
andStakeAuthorization
within the repository to determine the correct file name for coverage analysis.
Let's gather more context about how and where the StakeAuthorization implementation is defined. We'll list the files in the repository folder for the module and search within that directory for mentions of NewStakeAuthorization and StakeAuthorization. This will help us identify the correct file for coverage analysis.
StakeAuthorization Test Coverage Verified
The comprehensive tests in
x/mstaking/types/authz_test.go
cover the major functionalities of the StakeAuthorization implementation (located inx/mstaking/types/authz.go
), including:
- Creation via
NewStakeAuthorization
- Basic validation via
ValidateBasic
- Message acceptance with
Accept
- Message type URL handling with
MsgTypeURL
These tests assess both valid and error scenarios, ensuring thorough coverage.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check test coverage for StakeAuthorization implementation # Find the implementation file implementation_file=$(fd -t f -e go "stake_authorization.go" || true) if [ -n "$implementation_file" ]; then # Run tests with coverage go test -coverprofile=coverage.out ./x/mstaking/types -run "TestStakeAuthorization.*" # Show coverage for the implementation file go tool cover -func=coverage.out | grep "stake_authorization.go" fiLength of output: 78
Script:
#!/bin/bash echo "Searching for the definition of NewStakeAuthorization in x/mstaking/types..." rg "func NewStakeAuthorization" -g 'x/mstaking/types/' echo "--------------------------" echo "Searching for the definition of type StakeAuthorization in x/mstaking/types..." rg "type StakeAuthorization" -g 'x/mstaking/types/'Length of output: 795
Script:
#!/bin/bash echo "Listing all files in x/mstaking/types directory..." fd . x/mstaking/types echo "--------------------------" echo "Searching for 'NewStakeAuthorization' in x/mstaking/types directory..." rg "NewStakeAuthorization" x/mstaking/types echo "--------------------------" echo "Searching for 'StakeAuthorization' in x/mstaking/types directory..." rg "StakeAuthorization" x/mstaking/typesLength of output: 12634
func TestNewStakeAuthorization(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
allowedValidators []string | ||
deniedValidators []string | ||
authzType types.AuthorizationType | ||
amount sdk.Coins | ||
expectError bool | ||
}{ | ||
{ | ||
name: "valid authorization with allow list", | ||
allowedValidators: []string{"val1", "val2"}, | ||
deniedValidators: nil, | ||
authzType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | ||
amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | ||
expectError: false, | ||
}, | ||
{ | ||
name: "valid authorization with deny list", | ||
allowedValidators: nil, | ||
deniedValidators: []string{"val1", "val2"}, | ||
authzType: types.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE, | ||
amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | ||
expectError: false, | ||
}, | ||
} | ||
|
||
for _, tc := range tests { | ||
t.Run(tc.name, func(t *testing.T) { | ||
authorization, err := types.NewStakeAuthorization( | ||
tc.allowedValidators, | ||
tc.deniedValidators, | ||
tc.authzType, | ||
tc.amount, | ||
) | ||
|
||
if tc.expectError { | ||
require.Error(t, err) | ||
return | ||
} | ||
|
||
require.NoError(t, err) | ||
require.NotNil(t, authorization) | ||
|
||
if tc.allowedValidators != nil { | ||
require.NotNil(t, authorization.GetAllowList()) | ||
require.Equal(t, tc.allowedValidators, authorization.GetAllowList().Address) | ||
} | ||
|
||
if tc.deniedValidators != nil { | ||
require.NotNil(t, authorization.GetDenyList()) | ||
require.Equal(t, tc.deniedValidators, authorization.GetDenyList().Address) | ||
} | ||
|
||
require.Equal(t, tc.authzType, authorization.AuthorizationType) | ||
if tc.amount != nil { | ||
require.Equal(t, tc.amount, authorization.MaxTokens) | ||
} | ||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add test cases for error scenarios.
The test suite only covers positive cases. Consider adding test cases for:
- Mutually exclusive allow/deny lists
- Invalid validator addresses
- Empty validator lists
- Invalid authorization types
Example test case:
tests := []struct {
// ... existing fields ...
}{
// ... existing test cases ...
+ {
+ name: "invalid - both allow and deny lists",
+ allowedValidators: []string{"val1"},
+ deniedValidators: []string{"val2"},
+ authzType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE,
+ amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))),
+ expectError: true,
+ },
+ {
+ name: "invalid - empty validator list",
+ allowedValidators: []string{},
+ deniedValidators: nil,
+ authzType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE,
+ amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))),
+ expectError: true,
+ },
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func TestNewStakeAuthorization(t *testing.T) { | |
tests := []struct { | |
name string | |
allowedValidators []string | |
deniedValidators []string | |
authzType types.AuthorizationType | |
amount sdk.Coins | |
expectError bool | |
}{ | |
{ | |
name: "valid authorization with allow list", | |
allowedValidators: []string{"val1", "val2"}, | |
deniedValidators: nil, | |
authzType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | |
amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | |
expectError: false, | |
}, | |
{ | |
name: "valid authorization with deny list", | |
allowedValidators: nil, | |
deniedValidators: []string{"val1", "val2"}, | |
authzType: types.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE, | |
amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | |
expectError: false, | |
}, | |
} | |
for _, tc := range tests { | |
t.Run(tc.name, func(t *testing.T) { | |
authorization, err := types.NewStakeAuthorization( | |
tc.allowedValidators, | |
tc.deniedValidators, | |
tc.authzType, | |
tc.amount, | |
) | |
if tc.expectError { | |
require.Error(t, err) | |
return | |
} | |
require.NoError(t, err) | |
require.NotNil(t, authorization) | |
if tc.allowedValidators != nil { | |
require.NotNil(t, authorization.GetAllowList()) | |
require.Equal(t, tc.allowedValidators, authorization.GetAllowList().Address) | |
} | |
if tc.deniedValidators != nil { | |
require.NotNil(t, authorization.GetDenyList()) | |
require.Equal(t, tc.deniedValidators, authorization.GetDenyList().Address) | |
} | |
require.Equal(t, tc.authzType, authorization.AuthorizationType) | |
if tc.amount != nil { | |
require.Equal(t, tc.amount, authorization.MaxTokens) | |
} | |
}) | |
} | |
} | |
func TestNewStakeAuthorization(t *testing.T) { | |
tests := []struct { | |
name string | |
allowedValidators []string | |
deniedValidators []string | |
authzType types.AuthorizationType | |
amount sdk.Coins | |
expectError bool | |
}{ | |
{ | |
name: "valid authorization with allow list", | |
allowedValidators: []string{"val1", "val2"}, | |
deniedValidators: nil, | |
authzType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | |
amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | |
expectError: false, | |
}, | |
{ | |
name: "valid authorization with deny list", | |
allowedValidators: nil, | |
deniedValidators: []string{"val1", "val2"}, | |
authzType: types.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE, | |
amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | |
expectError: false, | |
}, | |
{ | |
name: "invalid - both allow and deny lists", | |
allowedValidators: []string{"val1"}, | |
deniedValidators: []string{"val2"}, | |
authzType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | |
amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | |
expectError: true, | |
}, | |
{ | |
name: "invalid - empty validator list", | |
allowedValidators: []string{}, | |
deniedValidators: nil, | |
authzType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | |
amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | |
expectError: true, | |
}, | |
} | |
for _, tc := range tests { | |
t.Run(tc.name, func(t *testing.T) { | |
authorization, err := types.NewStakeAuthorization( | |
tc.allowedValidators, | |
tc.deniedValidators, | |
tc.authzType, | |
tc.amount, | |
) | |
if tc.expectError { | |
require.Error(t, err) | |
return | |
} | |
require.NoError(t, err) | |
require.NotNil(t, authorization) | |
if tc.allowedValidators != nil { | |
require.NotNil(t, authorization.GetAllowList()) | |
require.Equal(t, tc.allowedValidators, authorization.GetAllowList().Address) | |
} | |
if tc.deniedValidators != nil { | |
require.NotNil(t, authorization.GetDenyList()) | |
require.Equal(t, tc.deniedValidators, authorization.GetDenyList().Address) | |
} | |
require.Equal(t, tc.authzType, authorization.AuthorizationType) | |
if tc.amount != nil { | |
require.Equal(t, tc.amount, authorization.MaxTokens) | |
} | |
}) | |
} | |
} |
name string | ||
auth types.StakeAuthorization | ||
msg sdk.Msg | ||
expectError bool | ||
}{ | ||
{ | ||
name: "valid delegate with allow list", | ||
auth: types.StakeAuthorization{ | ||
Validators: &types.StakeAuthorization_AllowList{ | ||
AllowList: &types.StakeAuthorization_Validators{ | ||
Address: []string{"val1"}, | ||
}, | ||
}, | ||
MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | ||
AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | ||
}, | ||
msg: &types.MsgDelegate{ | ||
DelegatorAddress: "delegator", | ||
ValidatorAddress: "val1", | ||
Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(500))), | ||
}, | ||
expectError: false, | ||
}, | ||
{ | ||
name: "invalid - validator not in allow list", | ||
auth: types.StakeAuthorization{ | ||
Validators: &types.StakeAuthorization_AllowList{ | ||
AllowList: &types.StakeAuthorization_Validators{ | ||
Address: []string{"val1"}, | ||
}, | ||
}, | ||
MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | ||
AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | ||
}, | ||
msg: &types.MsgDelegate{ | ||
DelegatorAddress: "delegator", | ||
ValidatorAddress: "val2", | ||
Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(500))), | ||
}, | ||
expectError: true, | ||
}, | ||
{ | ||
name: "invalid - validator in deny list", | ||
auth: types.StakeAuthorization{ | ||
Validators: &types.StakeAuthorization_DenyList{ | ||
DenyList: &types.StakeAuthorization_Validators{ | ||
Address: []string{"val1"}, | ||
}, | ||
}, | ||
MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | ||
AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | ||
}, | ||
msg: &types.MsgDelegate{ | ||
DelegatorAddress: "delegator", | ||
ValidatorAddress: "val1", | ||
Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(500))), | ||
}, | ||
expectError: true, | ||
}, | ||
{ | ||
name: "invalid - exceeds max tokens", | ||
auth: types.StakeAuthorization{ | ||
Validators: &types.StakeAuthorization_AllowList{ | ||
AllowList: &types.StakeAuthorization_Validators{ | ||
Address: []string{"val1"}, | ||
}, | ||
}, | ||
MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(400))), | ||
AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | ||
}, | ||
msg: &types.MsgDelegate{ | ||
DelegatorAddress: "delegator", | ||
ValidatorAddress: "val1", | ||
Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(500))), | ||
}, | ||
expectError: true, | ||
}, | ||
} | ||
|
||
for _, tc := range tests { | ||
t.Run(tc.name, func(t *testing.T) { | ||
resp, err := tc.auth.Accept(context.Background(), tc.msg) | ||
if tc.expectError { | ||
require.Error(t, err) | ||
return | ||
} | ||
|
||
require.NoError(t, err) | ||
require.True(t, resp.Accept) | ||
|
||
// Check if authorization should be deleted (when max tokens are used up) | ||
if tc.auth.MaxTokens != nil { | ||
msgCoins := tc.msg.(*types.MsgDelegate).Amount | ||
if tc.auth.MaxTokens.Equal(msgCoins) { | ||
require.True(t, resp.Delete) | ||
} | ||
} | ||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add test cases for message validation.
Add test cases for:
- Nil message
- Wrong message type
- Invalid delegator address
- Invalid amount denomination
Example test cases:
tests := []struct {
// ... existing fields ...
}{
// ... existing test cases ...
+ {
+ name: "invalid - nil message",
+ auth: types.StakeAuthorization{
+ MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))),
+ AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE,
+ },
+ msg: nil,
+ expectError: true,
+ },
+ {
+ name: "invalid - wrong message type",
+ auth: types.StakeAuthorization{
+ MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))),
+ AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE,
+ },
+ msg: &types.MsgUndelegate{},
+ expectError: true,
+ },
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func TestStakeAuthorization_Accept(t *testing.T) { | |
tests := []struct { | |
name string | |
auth types.StakeAuthorization | |
msg sdk.Msg | |
expectError bool | |
}{ | |
{ | |
name: "valid delegate with allow list", | |
auth: types.StakeAuthorization{ | |
Validators: &types.StakeAuthorization_AllowList{ | |
AllowList: &types.StakeAuthorization_Validators{ | |
Address: []string{"val1"}, | |
}, | |
}, | |
MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | |
AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | |
}, | |
msg: &types.MsgDelegate{ | |
DelegatorAddress: "delegator", | |
ValidatorAddress: "val1", | |
Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(500))), | |
}, | |
expectError: false, | |
}, | |
{ | |
name: "invalid - validator not in allow list", | |
auth: types.StakeAuthorization{ | |
Validators: &types.StakeAuthorization_AllowList{ | |
AllowList: &types.StakeAuthorization_Validators{ | |
Address: []string{"val1"}, | |
}, | |
}, | |
MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | |
AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | |
}, | |
msg: &types.MsgDelegate{ | |
DelegatorAddress: "delegator", | |
ValidatorAddress: "val2", | |
Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(500))), | |
}, | |
expectError: true, | |
}, | |
{ | |
name: "invalid - validator in deny list", | |
auth: types.StakeAuthorization{ | |
Validators: &types.StakeAuthorization_DenyList{ | |
DenyList: &types.StakeAuthorization_Validators{ | |
Address: []string{"val1"}, | |
}, | |
}, | |
MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | |
AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | |
}, | |
msg: &types.MsgDelegate{ | |
DelegatorAddress: "delegator", | |
ValidatorAddress: "val1", | |
Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(500))), | |
}, | |
expectError: true, | |
}, | |
{ | |
name: "invalid - exceeds max tokens", | |
auth: types.StakeAuthorization{ | |
Validators: &types.StakeAuthorization_AllowList{ | |
AllowList: &types.StakeAuthorization_Validators{ | |
Address: []string{"val1"}, | |
}, | |
}, | |
MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(400))), | |
AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | |
}, | |
msg: &types.MsgDelegate{ | |
DelegatorAddress: "delegator", | |
ValidatorAddress: "val1", | |
Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(500))), | |
}, | |
expectError: true, | |
}, | |
} | |
for _, tc := range tests { | |
t.Run(tc.name, func(t *testing.T) { | |
resp, err := tc.auth.Accept(context.Background(), tc.msg) | |
if tc.expectError { | |
require.Error(t, err) | |
return | |
} | |
require.NoError(t, err) | |
require.True(t, resp.Accept) | |
// Check if authorization should be deleted (when max tokens are used up) | |
if tc.auth.MaxTokens != nil { | |
msgCoins := tc.msg.(*types.MsgDelegate).Amount | |
if tc.auth.MaxTokens.Equal(msgCoins) { | |
require.True(t, resp.Delete) | |
} | |
} | |
}) | |
} | |
} | |
func TestStakeAuthorization_Accept(t *testing.T) { | |
tests := []struct { | |
name string | |
auth types.StakeAuthorization | |
msg sdk.Msg | |
expectError bool | |
}{ | |
{ | |
name: "valid delegate with allow list", | |
auth: types.StakeAuthorization{ | |
Validators: &types.StakeAuthorization_AllowList{ | |
AllowList: &types.StakeAuthorization_Validators{ | |
Address: []string{"val1"}, | |
}, | |
}, | |
MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | |
AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | |
}, | |
msg: &types.MsgDelegate{ | |
DelegatorAddress: "delegator", | |
ValidatorAddress: "val1", | |
Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(500))), | |
}, | |
expectError: false, | |
}, | |
{ | |
name: "invalid - validator not in allow list", | |
auth: types.StakeAuthorization{ | |
Validators: &types.StakeAuthorization_AllowList{ | |
AllowList: &types.StakeAuthorization_Validators{ | |
Address: []string{"val1"}, | |
}, | |
}, | |
MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | |
AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | |
}, | |
msg: &types.MsgDelegate{ | |
DelegatorAddress: "delegator", | |
ValidatorAddress: "val2", | |
Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(500))), | |
}, | |
expectError: true, | |
}, | |
{ | |
name: "invalid - validator in deny list", | |
auth: types.StakeAuthorization{ | |
Validators: &types.StakeAuthorization_DenyList{ | |
DenyList: &types.StakeAuthorization_Validators{ | |
Address: []string{"val1"}, | |
}, | |
}, | |
MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | |
AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | |
}, | |
msg: &types.MsgDelegate{ | |
DelegatorAddress: "delegator", | |
ValidatorAddress: "val1", | |
Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(500))), | |
}, | |
expectError: true, | |
}, | |
{ | |
name: "invalid - exceeds max tokens", | |
auth: types.StakeAuthorization{ | |
Validators: &types.StakeAuthorization_AllowList{ | |
AllowList: &types.StakeAuthorization_Validators{ | |
Address: []string{"val1"}, | |
}, | |
}, | |
MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(400))), | |
AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | |
}, | |
msg: &types.MsgDelegate{ | |
DelegatorAddress: "delegator", | |
ValidatorAddress: "val1", | |
Amount: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(500))), | |
}, | |
expectError: true, | |
}, | |
{ | |
name: "invalid - nil message", | |
auth: types.StakeAuthorization{ | |
MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | |
AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | |
}, | |
msg: nil, | |
expectError: true, | |
}, | |
{ | |
name: "invalid - wrong message type", | |
auth: types.StakeAuthorization{ | |
MaxTokens: sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(1000))), | |
AuthorizationType: types.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, | |
}, | |
msg: &types.MsgUndelegate{}, | |
expectError: true, | |
}, | |
} | |
for _, tc := range tests { | |
t.Run(tc.name, func(t *testing.T) { | |
resp, err := tc.auth.Accept(context.Background(), tc.msg) | |
if tc.expectError { | |
require.Error(t, err) | |
return | |
} | |
require.NoError(t, err) | |
require.True(t, resp.Accept) | |
// Check if authorization should be deleted (when max tokens are used up) | |
if tc.auth.MaxTokens != nil { | |
msgCoins := tc.msg.(*types.MsgDelegate).Amount | |
if tc.auth.MaxTokens.Equal(msgCoins) { | |
require.True(t, resp.Delete) | |
} | |
} | |
}) | |
} | |
} |
Implements comprehensive test suite for StakeAuthorization in the mstaking module. The tests cover:
This improves the overall test coverage and helps ensure the reliability of the staking authorization functionality.