/
example_test.go
205 lines (172 loc) · 7.08 KB
/
example_test.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
package integration_test
import (
"fmt"
"io"
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
"github.com/google/go-cmp/cmp"
"cosmossdk.io/core/appmodule"
"cosmossdk.io/log"
storetypes "cosmossdk.io/store/types"
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
"github.com/cosmos/cosmos-sdk/runtime"
"github.com/cosmos/cosmos-sdk/testutil/integration"
sdk "github.com/cosmos/cosmos-sdk/types"
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
"github.com/cosmos/cosmos-sdk/x/auth"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/mint"
mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
)
// Example shows how to use the integration test framework to test the integration of SDK modules.
// Panics are used in this example, but in a real test case, you should use the testing.T object and assertions.
func Example() {
// in this example we are testing the integration of the following modules:
// - mint, which directly depends on auth, bank and staking
encodingCfg := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, mint.AppModuleBasic{})
keys := storetypes.NewKVStoreKeys(authtypes.StoreKey, minttypes.StoreKey)
authority := authtypes.NewModuleAddress("gov").String()
// replace the logger by testing values in a real test case (e.g. log.NewTestLogger(t))
logger := log.NewNopLogger()
cms := integration.CreateMultiStore(keys, logger)
newCtx := sdk.NewContext(cms, cmtproto.Header{}, true, logger)
accountKeeper := authkeeper.NewAccountKeeper(
encodingCfg.Codec,
runtime.NewKVStoreService(keys[authtypes.StoreKey]),
authtypes.ProtoBaseAccount,
map[string][]string{minttypes.ModuleName: {authtypes.Minter}},
addresscodec.NewBech32Codec("cosmos"),
"cosmos",
authority,
)
// subspace is nil because we don't test params (which is legacy anyway)
authModule := auth.NewAppModule(encodingCfg.Codec, accountKeeper, authsims.RandomGenesisAccounts, nil)
// here bankkeeper and staking keeper is nil because we are not testing them
// subspace is nil because we don't test params (which is legacy anyway)
mintKeeper := mintkeeper.NewKeeper(encodingCfg.Codec, runtime.NewKVStoreService(keys[minttypes.StoreKey]), nil, accountKeeper, nil, authtypes.FeeCollectorName, authority)
mintModule := mint.NewAppModule(encodingCfg.Codec, mintKeeper, accountKeeper, nil, nil)
// create the application and register all the modules from the previous step
integrationApp := integration.NewIntegrationApp(
newCtx,
logger,
keys,
encodingCfg.Codec,
map[string]appmodule.AppModule{
authtypes.ModuleName: authModule,
minttypes.ModuleName: mintModule,
},
)
// register the message and query servers
authtypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), authkeeper.NewMsgServerImpl(accountKeeper))
minttypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), mintkeeper.NewMsgServerImpl(mintKeeper))
minttypes.RegisterQueryServer(integrationApp.QueryHelper(), mintkeeper.NewQueryServerImpl(mintKeeper))
params := minttypes.DefaultParams()
params.BlocksPerYear = 10000
// now we can use the application to test a mint message
result, err := integrationApp.RunMsg(&minttypes.MsgUpdateParams{
Authority: authority,
Params: params,
})
if err != nil {
panic(err)
}
// in this example the result is an empty response, a nil check is enough
// in other cases, it is recommended to check the result value.
if result == nil {
panic(fmt.Errorf("unexpected nil result"))
}
// we now check the result
resp := minttypes.MsgUpdateParamsResponse{}
err = encodingCfg.Codec.Unmarshal(result.Value, &resp)
if err != nil {
panic(err)
}
sdkCtx := sdk.UnwrapSDKContext(integrationApp.Context())
// we should also check the state of the application
got, err := mintKeeper.Params.Get(sdkCtx)
if err != nil {
panic(err)
}
if diff := cmp.Diff(got, params); diff != "" {
panic(diff)
}
fmt.Println(got.BlocksPerYear)
// Output: 10000
}
// ExampleOneModule shows how to use the integration test framework to test the integration of a single module.
// That module has no dependency on other modules.
func Example_oneModule() {
// in this example we are testing the integration of the auth module:
encodingCfg := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{})
keys := storetypes.NewKVStoreKeys(authtypes.StoreKey)
authority := authtypes.NewModuleAddress("gov").String()
// replace the logger by testing values in a real test case (e.g. log.NewTestLogger(t))
logger := log.NewLogger(io.Discard)
cms := integration.CreateMultiStore(keys, logger)
newCtx := sdk.NewContext(cms, cmtproto.Header{}, true, logger)
accountKeeper := authkeeper.NewAccountKeeper(
encodingCfg.Codec,
runtime.NewKVStoreService(keys[authtypes.StoreKey]),
authtypes.ProtoBaseAccount,
map[string][]string{minttypes.ModuleName: {authtypes.Minter}},
addresscodec.NewBech32Codec("cosmos"),
"cosmos",
authority,
)
// subspace is nil because we don't test params (which is legacy anyway)
authModule := auth.NewAppModule(encodingCfg.Codec, accountKeeper, authsims.RandomGenesisAccounts, nil)
// create the application and register all the modules from the previous step
integrationApp := integration.NewIntegrationApp(
newCtx,
logger,
keys,
encodingCfg.Codec,
map[string]appmodule.AppModule{
authtypes.ModuleName: authModule,
},
)
// register the message and query servers
authtypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), authkeeper.NewMsgServerImpl(accountKeeper))
params := authtypes.DefaultParams()
params.MaxMemoCharacters = 1000
// now we can use the application to test a mint message
result, err := integrationApp.RunMsg(&authtypes.MsgUpdateParams{
Authority: authority,
Params: params,
},
// this allows to the begin and end blocker of the module before and after the message
integration.WithAutomaticFinalizeBlock(),
// this allows to commit the state after the message
integration.WithAutomaticCommit(),
)
if err != nil {
panic(err)
}
// verify that the begin and end blocker were called
// NOTE: in this example, we are testing auth, which doesn't have any begin or end blocker
// so verifying the block height is enough
if integrationApp.LastBlockHeight() != 2 {
panic(fmt.Errorf("expected block height to be 2, got %d", integrationApp.LastBlockHeight()))
}
// in this example the result is an empty response, a nil check is enough
// in other cases, it is recommended to check the result value.
if result == nil {
panic(fmt.Errorf("unexpected nil result"))
}
// we now check the result
resp := authtypes.MsgUpdateParamsResponse{}
err = encodingCfg.Codec.Unmarshal(result.Value, &resp)
if err != nil {
panic(err)
}
sdkCtx := sdk.UnwrapSDKContext(integrationApp.Context())
// we should also check the state of the application
got := accountKeeper.GetParams(sdkCtx)
if diff := cmp.Diff(got, params); diff != "" {
panic(diff)
}
fmt.Println(got.MaxMemoCharacters)
// Output: 1000
}