cosmos-sdk/tests/integration/genutil/genaccount_test.go

299 lines
7.5 KiB
Go

package genutil
import (
"context"
"encoding/json"
"os"
"path"
"testing"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
corectx "cosmossdk.io/core/context"
"cosmossdk.io/log"
banktypes "cosmossdk.io/x/bank/types"
"github.com/cosmos/cosmos-sdk/client"
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
genutilhelpers "github.com/cosmos/cosmos-sdk/testutil/x/genutil"
sdk "github.com/cosmos/cosmos-sdk/types"
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/genutil"
genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
)
func TestAddGenesisAccountCmd(t *testing.T) {
_, _, addr1 := testdata.KeyTestPubAddr()
ac := codectestutil.CodecOptions{}.GetAddressCodec()
addr1Str, err := ac.BytesToString(addr1)
require.NoError(t, err)
tests := []struct {
name string
addr string
denom string
withKeyring bool
expectErr bool
}{
{
name: "invalid address",
addr: "",
denom: "1000atom",
withKeyring: false,
expectErr: true,
},
{
name: "valid address",
addr: addr1Str,
denom: "1000atom",
withKeyring: false,
expectErr: false,
},
{
name: "multiple denoms",
addr: addr1Str,
denom: "1000atom, 2000stake",
withKeyring: false,
expectErr: false,
},
{
name: "with keyring",
addr: "set",
denom: "1000atom",
withKeyring: true,
expectErr: false,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
home := t.TempDir()
logger := log.NewNopLogger()
v := viper.New()
encodingConfig := moduletestutil.MakeTestEncodingConfig(
codectestutil.CodecOptions{},
auth.AppModule{},
)
appCodec := encodingConfig.Codec
txConfig := encodingConfig.TxConfig
err = genutilhelpers.ExecInitCmd(testMbm, home, appCodec)
require.NoError(t, err)
err := writeAndTrackDefaultConfig(v, home)
require.NoError(t, err)
clientCtx := client.Context{}.WithCodec(appCodec).WithHomeDir(home).
WithAddressCodec(ac).WithTxConfig(txConfig)
if tc.withKeyring {
path := hd.CreateHDPath(118, 0, 0).String()
kr, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, home, nil, appCodec)
require.NoError(t, err)
_, _, err = kr.NewMnemonic(
tc.addr,
keyring.English,
path,
keyring.DefaultBIP39Passphrase,
hd.Secp256k1,
)
require.NoError(t, err)
clientCtx = clientCtx.WithKeyring(kr)
}
ctx := context.Background()
ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
ctx = context.WithValue(ctx, corectx.ViperContextKey, v)
ctx = context.WithValue(ctx, corectx.LoggerContextKey, logger)
cmd := genutilcli.AddGenesisAccountCmd()
cmd.SetArgs([]string{
tc.addr,
tc.denom,
})
if tc.expectErr {
require.Error(t, cmd.ExecuteContext(ctx))
} else {
require.NoError(t, cmd.ExecuteContext(ctx))
}
})
}
}
func TestBulkAddGenesisAccountCmd(t *testing.T) {
ac := codectestutil.CodecOptions{}.GetAddressCodec()
_, _, addr1 := testdata.KeyTestPubAddr()
_, _, addr2 := testdata.KeyTestPubAddr()
_, _, addr3 := testdata.KeyTestPubAddr()
addr1Str, err := ac.BytesToString(addr1)
require.NoError(t, err)
addr2Str, err := ac.BytesToString(addr2)
require.NoError(t, err)
addr3Str, err := ac.BytesToString(addr3)
require.NoError(t, err)
tests := []struct {
name string
state [][]genutil.GenesisAccount
expected map[string]sdk.Coins
appendFlag bool
expectErr bool
}{
{
name: "invalid address",
state: [][]genutil.GenesisAccount{
{
{
Address: "invalid",
Coins: sdk.NewCoins(sdk.NewInt64Coin("test", 1)),
},
},
},
expectErr: true,
},
{
name: "no append flag for multiple account adds",
state: [][]genutil.GenesisAccount{
{
{
Address: addr1Str,
Coins: sdk.NewCoins(sdk.NewInt64Coin("test", 1)),
},
},
{
{
Address: addr1Str,
Coins: sdk.NewCoins(sdk.NewInt64Coin("test", 2)),
},
},
},
appendFlag: false,
expectErr: true,
},
{
name: "multiple additions with append",
state: [][]genutil.GenesisAccount{
{
{
Address: addr1Str,
Coins: sdk.NewCoins(sdk.NewInt64Coin("test", 1)),
},
{
Address: addr2Str,
Coins: sdk.NewCoins(sdk.NewInt64Coin("test", 1)),
},
},
{
{
Address: addr1Str,
Coins: sdk.NewCoins(sdk.NewInt64Coin("test", 2)),
},
{
Address: addr2Str,
Coins: sdk.NewCoins(sdk.NewInt64Coin("stake", 1)),
},
{
Address: addr3Str,
Coins: sdk.NewCoins(sdk.NewInt64Coin("test", 1)),
},
},
},
expected: map[string]sdk.Coins{
addr1Str: sdk.NewCoins(sdk.NewInt64Coin("test", 3)),
addr2Str: sdk.NewCoins(sdk.NewInt64Coin("test", 1), sdk.NewInt64Coin("stake", 1)),
addr3Str: sdk.NewCoins(sdk.NewInt64Coin("test", 1)),
},
appendFlag: true,
expectErr: false,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
home := t.TempDir()
logger := log.NewNopLogger()
v := viper.New()
encodingConfig := moduletestutil.MakeTestEncodingConfig(
codectestutil.CodecOptions{},
auth.AppModule{},
)
appCodec := encodingConfig.Codec
txConfig := encodingConfig.TxConfig
err = genutilhelpers.ExecInitCmd(testMbm, home, appCodec)
require.NoError(t, err)
err = writeAndTrackDefaultConfig(v, home)
require.NoError(t, err)
clientCtx := client.Context{}.WithCodec(appCodec).WithHomeDir(home).
WithAddressCodec(ac).WithTxConfig(txConfig)
ctx := context.Background()
ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
ctx = context.WithValue(ctx, corectx.ViperContextKey, v)
ctx = context.WithValue(ctx, corectx.LoggerContextKey, logger)
// The first iteration (pre-append) may not error.
// Check if any errors after all state transitions to genesis.
doesErr := false
// apply multiple state iterations if applicable (e.g. --append)
for _, state := range tc.state {
bz, err := json.Marshal(state)
require.NoError(t, err)
filePath := path.Join(home, "accounts.json")
err = os.WriteFile(filePath, bz, 0o600)
require.NoError(t, err)
cmd := genutilcli.AddBulkGenesisAccountCmd()
args := []string{filePath}
if tc.appendFlag {
args = append(args, "--append")
}
cmd.SetArgs(args)
err = cmd.ExecuteContext(ctx)
if err != nil {
doesErr = true
}
}
require.Equal(t, tc.expectErr, doesErr)
// an error already occurred, no need to check the state
if doesErr {
return
}
appState, _, err := genutiltypes.GenesisStateFromGenFile(path.Join(home, "config", "genesis.json"))
require.NoError(t, err)
bankState := banktypes.GetGenesisStateFromAppState(encodingConfig.Codec, appState)
require.EqualValues(t, len(tc.expected), len(bankState.Balances))
for _, acc := range bankState.Balances {
require.True(
t,
tc.expected[acc.Address].Equal(acc.Coins),
"expected: %v, got: %v",
tc.expected[acc.Address],
acc.Coins,
)
}
expectedSupply := sdk.NewCoins()
for _, coins := range tc.expected {
expectedSupply = expectedSupply.Add(coins...)
}
require.Equal(t, expectedSupply, bankState.Supply)
})
}
}