2020-03-11 19:52:25 +00:00
package keeper_test
import (
"reflect"
2020-03-12 17:05:40 +00:00
"time"
2020-03-11 19:52:25 +00:00
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/kava-labs/kava/app"
"github.com/kava-labs/kava/x/committee/types"
)
func ( suite * KeeperTestSuite ) TestSubmitProposal ( ) {
normalCom := types . Committee {
ID : 12 ,
Members : suite . addresses [ : 2 ] ,
Permissions : [ ] types . Permission { types . GodPermission { } } ,
}
noPermissionsCom := types . Committee {
ID : 12 ,
Members : suite . addresses [ : 2 ] ,
Permissions : [ ] types . Permission { } ,
}
testcases := [ ] struct {
name string
committee types . Committee
pubProposal types . PubProposal
proposer sdk . AccAddress
committeeID uint64
expectPass bool
} {
{
name : "normal" ,
committee : normalCom ,
pubProposal : gov . NewTextProposal ( "A Title" , "A description of this proposal." ) ,
proposer : normalCom . Members [ 0 ] ,
committeeID : normalCom . ID ,
expectPass : true ,
} ,
{
name : "invalid proposal" ,
committee : normalCom ,
pubProposal : nil ,
proposer : normalCom . Members [ 0 ] ,
committeeID : normalCom . ID ,
expectPass : false ,
} ,
{
name : "missing committee" ,
// no committee
pubProposal : gov . NewTextProposal ( "A Title" , "A description of this proposal." ) ,
proposer : suite . addresses [ 0 ] ,
committeeID : 0 ,
expectPass : false ,
} ,
{
name : "not a member" ,
committee : normalCom ,
pubProposal : gov . NewTextProposal ( "A Title" , "A description of this proposal." ) ,
proposer : suite . addresses [ 4 ] ,
committeeID : normalCom . ID ,
expectPass : false ,
} ,
{
name : "not enough permissions" ,
committee : noPermissionsCom ,
pubProposal : gov . NewTextProposal ( "A Title" , "A description of this proposal." ) ,
proposer : noPermissionsCom . Members [ 0 ] ,
committeeID : noPermissionsCom . ID ,
expectPass : false ,
} ,
}
for _ , tc := range testcases {
suite . Run ( tc . name , func ( ) {
// Create local testApp because suite doesn't run the SetupTest function for subtests, which would mean the app state is not be reset between subtests.
tApp := app . NewTestApp ( )
keeper := tApp . GetCommitteeKeeper ( )
ctx := tApp . NewContext ( true , abci . Header { } )
tApp . InitializeFromGenesisStates ( )
// setup committee (if required)
if ! ( reflect . DeepEqual ( tc . committee , types . Committee { } ) ) {
keeper . SetCommittee ( ctx , tc . committee )
}
id , err := keeper . SubmitProposal ( ctx , tc . proposer , tc . committeeID , tc . pubProposal )
if tc . expectPass {
suite . NoError ( err )
2020-03-12 17:05:40 +00:00
pr , found := keeper . GetProposal ( ctx , id )
2020-03-11 19:52:25 +00:00
suite . True ( found )
2020-03-12 17:05:40 +00:00
suite . Equal ( tc . committeeID , pr . CommitteeID )
suite . Equal ( ctx . BlockTime ( ) . Add ( types . MaxProposalDuration ) , pr . Deadline )
2020-03-11 19:52:25 +00:00
} else {
suite . NotNil ( err )
}
} )
}
}
func ( suite * KeeperTestSuite ) TestAddVote ( ) {
normalCom := types . Committee {
ID : 12 ,
Members : suite . addresses [ : 2 ] ,
Permissions : [ ] types . Permission { types . GodPermission { } } ,
}
2020-03-12 17:05:40 +00:00
firstBlockTime := time . Date ( 1998 , time . January , 1 , 1 , 0 , 0 , 0 , time . UTC )
2020-03-11 19:52:25 +00:00
testcases := [ ] struct {
name string
proposalID uint64
voter sdk . AccAddress
2020-03-12 17:05:40 +00:00
voteTime time . Time
2020-03-11 19:52:25 +00:00
expectPass bool
} {
{
name : "normal" ,
proposalID : types . DefaultNextProposalID ,
voter : normalCom . Members [ 0 ] ,
expectPass : true ,
} ,
{
name : "nonexistent proposal" ,
proposalID : 9999999 ,
voter : normalCom . Members [ 0 ] ,
expectPass : false ,
} ,
{
name : "voter not committee member" ,
proposalID : types . DefaultNextProposalID ,
voter : suite . addresses [ 4 ] ,
expectPass : false ,
} ,
2020-03-12 17:05:40 +00:00
{
name : "proposal expired" ,
proposalID : types . DefaultNextProposalID ,
voter : normalCom . Members [ 0 ] ,
voteTime : firstBlockTime . Add ( types . MaxProposalDuration ) ,
expectPass : false ,
} ,
2020-03-11 19:52:25 +00:00
}
for _ , tc := range testcases {
suite . Run ( tc . name , func ( ) {
// Create local testApp because suite doesn't run the SetupTest function for subtests, which would mean the app state is not be reset between subtests.
tApp := app . NewTestApp ( )
keeper := tApp . GetCommitteeKeeper ( )
2020-03-12 17:05:40 +00:00
ctx := tApp . NewContext ( true , abci . Header { Height : 1 , Time : firstBlockTime } )
2020-03-11 19:52:25 +00:00
tApp . InitializeFromGenesisStates ( )
// setup the committee and proposal
keeper . SetCommittee ( ctx , normalCom )
_ , err := keeper . SubmitProposal ( ctx , normalCom . Members [ 0 ] , normalCom . ID , gov . NewTextProposal ( "A Title" , "A description of this proposal." ) )
suite . NoError ( err )
2020-03-12 17:05:40 +00:00
ctx = ctx . WithBlockTime ( tc . voteTime )
2020-03-11 19:52:25 +00:00
err = keeper . AddVote ( ctx , tc . proposalID , tc . voter )
if tc . expectPass {
suite . NoError ( err )
_ , found := keeper . GetVote ( ctx , tc . proposalID , tc . voter )
suite . True ( found )
} else {
suite . NotNil ( err )
}
} )
}
}
func ( suite * KeeperTestSuite ) TestCloseOutProposal ( ) {
// setup test
suite . app . InitializeFromGenesisStates ( )
// TODO replace below with genesis state
normalCom := types . Committee {
ID : 12 ,
Members : suite . addresses [ : 2 ] ,
Permissions : [ ] types . Permission { types . GodPermission { } } ,
}
suite . keeper . SetCommittee ( suite . ctx , normalCom )
pprop := gov . NewTextProposal ( "A Title" , "A description of this proposal." )
id , err := suite . keeper . SubmitProposal ( suite . ctx , normalCom . Members [ 0 ] , normalCom . ID , pprop )
suite . NoError ( err )
err = suite . keeper . AddVote ( suite . ctx , id , normalCom . Members [ 0 ] )
suite . NoError ( err )
err = suite . keeper . AddVote ( suite . ctx , id , normalCom . Members [ 1 ] )
suite . NoError ( err )
// run test
err = suite . keeper . CloseOutProposal ( suite . ctx , id )
// check
suite . NoError ( err )
_ , found := suite . keeper . GetProposal ( suite . ctx , id )
suite . False ( found )
suite . keeper . IterateVotes ( suite . ctx , id , func ( v types . Vote ) bool {
suite . Fail ( "found vote when none should exist" )
return false
} )
}
type UnregisteredProposal struct {
gov . TextProposal
}
func ( UnregisteredProposal ) ProposalRoute ( ) string { return "unregistered" }
func ( UnregisteredProposal ) ProposalType ( ) string { return "unregistered" }
var _ types . PubProposal = UnregisteredProposal { }
func ( suite * KeeperTestSuite ) TestValidatePubProposal ( ) {
testcases := [ ] struct {
name string
pubProposal types . PubProposal
expectPass bool
} {
{
name : "valid" ,
pubProposal : gov . NewTextProposal ( "A Title" , "A description of this proposal." ) ,
expectPass : true ,
} ,
{
name : "invalid (missing title)" ,
pubProposal : gov . TextProposal { Description : "A description of this proposal." } ,
expectPass : false ,
} ,
{
name : "invalid (unregistered)" ,
pubProposal : UnregisteredProposal { gov . TextProposal { Title : "A Title" , Description : "A description of this proposal." } } ,
expectPass : false ,
} ,
{
name : "invalid (nil)" ,
pubProposal : nil ,
expectPass : false ,
} ,
// TODO test case when the handler fails
}
for _ , tc := range testcases {
suite . Run ( tc . name , func ( ) {
err := suite . keeper . ValidatePubProposal ( suite . ctx , tc . pubProposal )
if tc . expectPass {
suite . NoError ( err )
} else {
suite . NotNil ( err )
}
} )
}
}