-
Notifications
You must be signed in to change notification settings - Fork 0
/
suite.go
213 lines (175 loc) · 8.74 KB
/
suite.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
package testutil
import (
"fmt"
"reflect"
"time"
"github.com/furya-official/mage/app"
"github.com/furya-official/mage/x/swap/keeper"
"github.com/furya-official/mage/x/swap/types"
sdk "github.com/cosmos/cosmos-sdk/types"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
BankKeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/stretchr/testify/suite"
abci "github.com/tendermint/tendermint/abci/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmtime "github.com/tendermint/tendermint/types/time"
)
var defaultSwapFee = sdk.MustNewDecFromStr("0.003")
// Suite implements a test suite for the swap module integration tests
type Suite struct {
suite.Suite
Keeper keeper.Keeper
App app.TestApp
Ctx sdk.Context
BankKeeper BankKeeper.Keeper
AccountKeeper authkeeper.AccountKeeper
}
// SetupTest instantiates a new app, keepers, and sets suite state
func (suite *Suite) SetupTest() {
tApp := app.NewTestApp()
ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: tmtime.Now()})
suite.Ctx = ctx
suite.App = tApp
suite.Keeper = tApp.GetSwapKeeper()
suite.BankKeeper = tApp.GetBankKeeper()
suite.AccountKeeper = tApp.GetAccountKeeper()
}
// GetEvents returns emitted events on the sdk context
func (suite *Suite) GetEvents() sdk.Events {
return suite.Ctx.EventManager().Events()
}
// AddCoinsToModule adds coins to the swap module account
func (suite *Suite) AddCoinsToModule(amount sdk.Coins) {
// Does not use suite.BankKeeper.MintCoins as module account would not have permission to mint
err := suite.App.FundModuleAccount(suite.Ctx, types.ModuleName, amount)
suite.Require().NoError(err)
}
// RemoveCoinsFromModule removes coins to the swap module account
func (suite *Suite) RemoveCoinsFromModule(amount sdk.Coins) {
// Swap module does not have BurnCoins permission so we need to transfer to gov first to burn
err := suite.BankKeeper.SendCoinsFromModuleToModule(suite.Ctx, types.ModuleAccountName, govtypes.ModuleName, amount)
suite.Require().NoError(err)
err = suite.BankKeeper.BurnCoins(suite.Ctx, govtypes.ModuleName, amount)
suite.Require().NoError(err)
}
// CreateAccount creates a new account from the provided balance
func (suite *Suite) CreateAccount(initialBalance sdk.Coins) authtypes.AccountI {
_, addrs := app.GeneratePrivKeyAddressPairs(1)
ak := suite.App.GetAccountKeeper()
acc := ak.NewAccountWithAddress(suite.Ctx, addrs[0])
ak.SetAccount(suite.Ctx, acc)
err := suite.App.FundAccount(suite.Ctx, acc.GetAddress(), initialBalance)
suite.Require().NoError(err)
return acc
}
// NewAccountFromAddr creates a new account from the provided address with the provided balance
func (suite *Suite) NewAccountFromAddr(addr sdk.AccAddress, balance sdk.Coins) authtypes.AccountI {
ak := suite.App.GetAccountKeeper()
acc := ak.NewAccountWithAddress(suite.Ctx, addr)
ak.SetAccount(suite.Ctx, acc)
err := suite.App.FundAccount(suite.Ctx, acc.GetAddress(), balance)
suite.Require().NoError(err)
return acc
}
// CreateVestingAccount creates a new vesting account from the provided balance and vesting balance
func (suite *Suite) CreateVestingAccount(initialBalance sdk.Coins, vestingBalance sdk.Coins) authtypes.AccountI {
acc := suite.CreateAccount(initialBalance)
bacc := acc.(*authtypes.BaseAccount)
periods := vestingtypes.Periods{
vestingtypes.Period{
Length: 31556952,
Amount: vestingBalance,
},
}
vacc := vestingtypes.NewPeriodicVestingAccount(bacc, initialBalance, time.Now().Unix(), periods) // TODO is initialBalance correct for originalVesting?
return vacc
}
// CreatePool creates a pool and stores it in state with the provided reserves
func (suite *Suite) CreatePool(reserves sdk.Coins) error {
depositor := suite.CreateAccount(reserves)
pool := types.NewAllowedPool(reserves[0].Denom, reserves[1].Denom)
suite.Require().NoError(pool.Validate())
suite.Keeper.SetParams(suite.Ctx, types.NewParams(types.AllowedPools{pool}, defaultSwapFee))
return suite.Keeper.Deposit(suite.Ctx, depositor.GetAddress(), reserves[0], reserves[1], sdk.MustNewDecFromStr("1"))
}
// AccountBalanceEqual asserts that the coins match the account balance
func (suite *Suite) AccountBalanceEqual(addr sdk.AccAddress, coins sdk.Coins) {
balance := suite.BankKeeper.GetAllBalances(suite.Ctx, addr)
suite.Equal(coins, balance, fmt.Sprintf("expected account balance to equal coins %s, but got %s", coins, balance))
}
// ModuleAccountBalanceEqual asserts that the swap module account balance matches the provided coins
func (suite *Suite) ModuleAccountBalanceEqual(coins sdk.Coins) {
balance := suite.BankKeeper.GetAllBalances(
suite.Ctx,
suite.AccountKeeper.GetModuleAddress(types.ModuleAccountName),
)
suite.Equal(coins, balance, fmt.Sprintf("expected module account balance to equal coins %s, but got %s", coins, balance))
}
// PoolLiquidityEqual asserts that the pool matching the provided coins has those reserves
func (suite *Suite) PoolLiquidityEqual(coins sdk.Coins) {
poolRecord, ok := suite.Keeper.GetPool(suite.Ctx, types.PoolIDFromCoins(coins))
suite.Require().True(ok, "expected pool to exist")
reserves := sdk.NewCoins(poolRecord.ReservesA, poolRecord.ReservesB)
suite.Equal(coins, reserves, fmt.Sprintf("expected pool reserves of %s, got %s", coins, reserves))
}
// PoolDeleted asserts that the pool does not exist
func (suite *Suite) PoolDeleted(denomA, denomB string) {
_, ok := suite.Keeper.GetPool(suite.Ctx, types.PoolID(denomA, denomB))
suite.Require().False(ok, "expected pool to not exist")
}
// PoolShareTotalEqual asserts the total shares match the stored pool
func (suite *Suite) PoolShareTotalEqual(poolID string, totalShares sdk.Int) {
poolRecord, found := suite.Keeper.GetPool(suite.Ctx, poolID)
suite.Require().True(found, fmt.Sprintf("expected pool %s to exist", poolID))
suite.Equal(totalShares, poolRecord.TotalShares, "expected pool total shares to be equal")
}
// PoolDepositorSharesEqual asserts the depositor owns the shares for the provided pool
func (suite *Suite) PoolDepositorSharesEqual(depositor sdk.AccAddress, poolID string, shares sdk.Int) {
shareRecord, found := suite.Keeper.GetDepositorShares(suite.Ctx, depositor, poolID)
suite.Require().True(found, fmt.Sprintf("expected share record to exist for depositor %s and pool %s", depositor.String(), poolID))
suite.Equal(shares, shareRecord.SharesOwned)
}
// PoolReservesEqual assets the stored pool reserves are equal to the provided reserves
func (suite *Suite) PoolReservesEqual(poolID string, reserves sdk.Coins) {
poolRecord, found := suite.Keeper.GetPool(suite.Ctx, poolID)
suite.Require().True(found, fmt.Sprintf("expected pool %s to exist", poolID))
suite.Equal(reserves, poolRecord.Reserves(), "expected pool reserves to be equal")
}
// PoolShareValueEqual asserts that the depositor shares are in state and the value matches the expected coins
func (suite *Suite) PoolShareValueEqual(depositor authtypes.AccountI, pool types.AllowedPool, coins sdk.Coins) {
poolRecord, ok := suite.Keeper.GetPool(suite.Ctx, pool.Name())
suite.Require().True(ok, fmt.Sprintf("expected pool %s to exist", pool.Name()))
shares, ok := suite.Keeper.GetDepositorShares(suite.Ctx, depositor.GetAddress(), poolRecord.PoolID)
suite.Require().True(ok, fmt.Sprintf("expected shares to exist for depositor %s", depositor.GetAddress()))
storedPool, err := types.NewDenominatedPoolWithExistingShares(sdk.NewCoins(poolRecord.ReservesA, poolRecord.ReservesB), poolRecord.TotalShares)
suite.Nil(err)
value := storedPool.ShareValue(shares.SharesOwned)
suite.Equal(coins, value, fmt.Sprintf("expected shares to equal %s, but got %s", coins, value))
}
// PoolSharesDeleted asserts that the pool shares have been removed
func (suite *Suite) PoolSharesDeleted(depositor sdk.AccAddress, denomA, denomB string) {
_, ok := suite.Keeper.GetDepositorShares(suite.Ctx, depositor, types.PoolID(denomA, denomB))
suite.Require().False(ok, "expected pool shares to not exist")
}
// EventsContains asserts that the expected event is in the provided events
func (suite *Suite) EventsContains(events sdk.Events, expectedEvent sdk.Event) {
foundMatch := false
for _, event := range events {
if event.Type == expectedEvent.Type {
if reflect.DeepEqual(attrsToMap(expectedEvent.Attributes), attrsToMap(event.Attributes)) {
foundMatch = true
}
}
}
suite.True(foundMatch, fmt.Sprintf("event of type %s not found or did not match", expectedEvent.Type))
}
func attrsToMap(attrs []abci.EventAttribute) []sdk.Attribute { // new cosmos changed the event attribute type
out := []sdk.Attribute{}
for _, attr := range attrs {
out = append(out, sdk.NewAttribute(string(attr.Key), string(attr.Value)))
}
return out
}