github.com/Finschia/finschia-sdk@v0.48.1/x/foundation/client/testutil/suite.go (about) 1 package testutil 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "time" 7 8 "github.com/stretchr/testify/suite" 9 10 "github.com/Finschia/finschia-sdk/crypto/hd" 11 "github.com/Finschia/finschia-sdk/crypto/keyring" 12 "github.com/Finschia/finschia-sdk/testutil/network" 13 "github.com/Finschia/finschia-sdk/testutil/testdata" 14 15 "github.com/Finschia/finschia-sdk/client/flags" 16 clitestutil "github.com/Finschia/finschia-sdk/testutil/cli" 17 sdk "github.com/Finschia/finschia-sdk/types" 18 bankcli "github.com/Finschia/finschia-sdk/x/bank/client/cli" 19 "github.com/Finschia/finschia-sdk/x/foundation" 20 "github.com/Finschia/finschia-sdk/x/foundation/client/cli" 21 ) 22 23 type IntegrationTestSuite struct { 24 suite.Suite 25 26 cfg network.Config 27 network *network.Network 28 29 setupHeight int64 30 31 authority sdk.AccAddress 32 comingMember sdk.AccAddress 33 leavingMember sdk.AccAddress 34 permanentMember sdk.AccAddress 35 stranger sdk.AccAddress 36 37 proposalID uint64 38 } 39 40 var commonArgs = []string{ 41 fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), 42 fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), 43 fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)))), 44 } 45 46 func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { 47 return &IntegrationTestSuite{cfg: cfg} 48 } 49 50 func (s *IntegrationTestSuite) SetupSuite() { 51 s.T().Log("setting up integration test suite") 52 testdata.RegisterInterfaces(s.cfg.InterfaceRegistry) 53 54 genesisState := s.cfg.GenesisState 55 56 var foundationData foundation.GenesisState 57 s.Require().NoError(s.cfg.Codec.UnmarshalJSON(genesisState[foundation.ModuleName], &foundationData)) 58 59 // enable foundation tax 60 params := foundation.Params{ 61 FoundationTax: sdk.MustNewDecFromStr("0.2"), 62 } 63 foundationData.Params = params 64 65 var strangerMnemonic string 66 strangerMnemonic, s.stranger = s.createMnemonic("stranger") 67 var leavingMemberMnemonic string 68 leavingMemberMnemonic, s.leavingMember = s.createMnemonic("leavingmember") 69 var permanentMemberMnemonic string 70 permanentMemberMnemonic, s.permanentMember = s.createMnemonic("permanentmember") 71 72 foundationData.Members = []foundation.Member{ 73 { 74 Address: s.leavingMember.String(), 75 Metadata: "leaving member", 76 }, 77 { 78 Address: s.permanentMember.String(), 79 Metadata: "permanent member", 80 }, 81 } 82 83 info := foundation.DefaultFoundation() 84 info.TotalWeight = sdk.NewDecFromInt(sdk.NewInt(int64(len(foundationData.Members)))) 85 info.SetDecisionPolicy(&foundation.ThresholdDecisionPolicy{ 86 Threshold: sdk.OneDec(), 87 Windows: &foundation.DecisionPolicyWindows{ 88 VotingPeriod: 7 * 24 * time.Hour, 89 }, 90 }) 91 foundationData.Foundation = info 92 93 // enable censorship 94 censorships := []foundation.Censorship{ 95 { 96 MsgTypeUrl: sdk.MsgTypeURL((*foundation.MsgWithdrawFromTreasury)(nil)), 97 Authority: foundation.CensorshipAuthorityFoundation, 98 }, 99 } 100 foundationData.Censorships = censorships 101 102 treasuryReceivers := []sdk.AccAddress{s.stranger, s.leavingMember} 103 for _, receiver := range treasuryReceivers { 104 ga := foundation.GrantAuthorization{ 105 Grantee: receiver.String(), 106 }.WithAuthorization(&foundation.ReceiveFromTreasuryAuthorization{}) 107 s.Require().NotNil(ga) 108 foundationData.Authorizations = append(foundationData.Authorizations, *ga) 109 } 110 111 foundationDataBz, err := s.cfg.Codec.MarshalJSON(&foundationData) 112 s.Require().NoError(err) 113 genesisState[foundation.ModuleName] = foundationDataBz 114 s.cfg.GenesisState = genesisState 115 116 s.network = network.New(s.T(), s.cfg) 117 118 _, err = s.network.WaitForHeight(1) 119 s.Require().NoError(err) 120 121 var comingMemberMnemonic string 122 comingMemberMnemonic, s.comingMember = s.createMnemonic("comingmember") 123 124 s.authority = foundation.DefaultAuthority() 125 s.createAccount("stranger", strangerMnemonic) 126 s.createAccount("comingmember", comingMemberMnemonic) 127 s.createAccount("leavingmember", leavingMemberMnemonic) 128 s.createAccount("permanentmember", permanentMemberMnemonic) 129 130 s.proposalID = s.submitProposal(testdata.NewTestMsg(s.authority), false) 131 s.vote(s.proposalID, []sdk.AccAddress{s.leavingMember, s.permanentMember}) 132 s.Require().NoError(s.network.WaitForNextBlock()) 133 134 s.setupHeight, err = s.network.LatestHeight() 135 s.Require().NoError(err) 136 s.Require().NoError(s.network.WaitForNextBlock()) 137 } 138 139 func (s *IntegrationTestSuite) TearDownSuite() { 140 s.T().Log("tearing down integration test suite") 141 s.network.Cleanup() 142 } 143 144 // submit a proposal 145 func (s *IntegrationTestSuite) submitProposal(msg sdk.Msg, try bool) uint64 { 146 val := s.network.Validators[0] 147 148 proposers := []string{s.permanentMember.String()} 149 proposersBz, err := json.Marshal(&proposers) 150 s.Require().NoError(err) 151 152 args := append([]string{ 153 "test proposal", 154 string(proposersBz), 155 s.msgToString(msg), 156 }, commonArgs...) 157 if try { 158 args = append(args, fmt.Sprintf("--%s=%s", cli.FlagExec, cli.ExecTry)) 159 } 160 out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.NewTxCmdSubmitProposal(), args) 161 s.Require().NoError(err) 162 163 var res sdk.TxResponse 164 s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &res), out.String()) 165 s.Require().Zero(res.Code, out.String()) 166 167 events := res.Logs[0].Events 168 proposalEvent, _ := sdk.TypedEventToEvent(&foundation.EventSubmitProposal{}) 169 for _, e := range events { 170 if e.Type == proposalEvent.Type { 171 var proposal foundation.Proposal 172 err := val.ClientCtx.Codec.UnmarshalJSON([]byte(e.Attributes[0].Value), &proposal) 173 s.Require().NoError(err) 174 175 return proposal.Id 176 } 177 } 178 panic("You cannot reach here") 179 } 180 181 func (s *IntegrationTestSuite) vote(proposalID uint64, voters []sdk.AccAddress) { 182 val := s.network.Validators[0] 183 184 for _, voter := range voters { 185 args := append([]string{ 186 fmt.Sprint(proposalID), 187 voter.String(), 188 foundation.VOTE_OPTION_YES.String(), 189 "test vote", 190 }, commonArgs...) 191 out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.NewTxCmdVote(), args) 192 s.Require().NoError(err) 193 194 var res sdk.TxResponse 195 s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &res), out.String()) 196 s.Require().Zero(res.Code, out.String()) 197 } 198 } 199 200 func (s *IntegrationTestSuite) msgToString(msg sdk.Msg) string { 201 anyJSON, err := s.cfg.Codec.MarshalInterfaceJSON(msg) 202 s.Require().NoError(err) 203 204 cliMsgs := []json.RawMessage{anyJSON} 205 msgsBz, err := json.Marshal(cliMsgs) 206 s.Require().NoError(err) 207 208 return string(msgsBz) 209 } 210 211 // creates an account 212 func (s *IntegrationTestSuite) createMnemonic(uid string) (string, sdk.AccAddress) { 213 cstore := keyring.NewInMemory() 214 info, mnemonic, err := cstore.NewMnemonic(uid, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) 215 s.Require().NoError(err) 216 217 return mnemonic, info.GetAddress() 218 } 219 220 // creates an account and send some coins to it for the future transactions. 221 func (s *IntegrationTestSuite) createAccount(uid, mnemonic string) { 222 val := s.network.Validators[0] 223 info, err := val.ClientCtx.Keyring.NewAccount(uid, mnemonic, keyring.DefaultBIP39Passphrase, sdk.FullFundraiserPath, hd.Secp256k1) 224 s.Require().NoError(err) 225 226 addr := info.GetAddress() 227 fee := sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(1000))) 228 args := append([]string{ 229 val.Address.String(), 230 addr.String(), 231 fee.String(), 232 fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address), 233 }, commonArgs...) 234 out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, bankcli.NewSendTxCmd(), args) 235 s.Require().NoError(err) 236 237 var res sdk.TxResponse 238 s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &res), out.String()) 239 s.Require().Zero(res.Code, out.String()) 240 }