github.com/cosmos/cosmos-sdk@v0.50.10/x/genutil/client/cli/genaccount_test.go (about)

     1  package cli_test
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"os"
     8  	"path"
     9  	"testing"
    10  
    11  	"github.com/spf13/viper"
    12  	"github.com/stretchr/testify/require"
    13  
    14  	"cosmossdk.io/log"
    15  
    16  	"github.com/cosmos/cosmos-sdk/client"
    17  	"github.com/cosmos/cosmos-sdk/client/flags"
    18  	addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
    19  	"github.com/cosmos/cosmos-sdk/crypto/hd"
    20  	"github.com/cosmos/cosmos-sdk/crypto/keyring"
    21  	"github.com/cosmos/cosmos-sdk/server"
    22  	"github.com/cosmos/cosmos-sdk/testutil/testdata"
    23  	sdk "github.com/cosmos/cosmos-sdk/types"
    24  	moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
    25  	"github.com/cosmos/cosmos-sdk/x/auth"
    26  	banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
    27  	"github.com/cosmos/cosmos-sdk/x/genutil"
    28  	genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
    29  	genutiltest "github.com/cosmos/cosmos-sdk/x/genutil/client/testutil"
    30  	genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
    31  )
    32  
    33  func TestAddGenesisAccountCmd(t *testing.T) {
    34  	_, _, addr1 := testdata.KeyTestPubAddr()
    35  	tests := []struct {
    36  		name        string
    37  		addr        string
    38  		denom       string
    39  		withKeyring bool
    40  		expectErr   bool
    41  	}{
    42  		{
    43  			name:        "invalid address",
    44  			addr:        "",
    45  			denom:       "1000atom",
    46  			withKeyring: false,
    47  			expectErr:   true,
    48  		},
    49  		{
    50  			name:        "valid address",
    51  			addr:        addr1.String(),
    52  			denom:       "1000atom",
    53  			withKeyring: false,
    54  			expectErr:   false,
    55  		},
    56  		{
    57  			name:        "multiple denoms",
    58  			addr:        addr1.String(),
    59  			denom:       "1000atom, 2000stake",
    60  			withKeyring: false,
    61  			expectErr:   false,
    62  		},
    63  		{
    64  			name:        "with keyring",
    65  			addr:        "ser",
    66  			denom:       "1000atom",
    67  			withKeyring: true,
    68  			expectErr:   false,
    69  		},
    70  	}
    71  
    72  	for _, tc := range tests {
    73  		tc := tc
    74  		t.Run(tc.name, func(t *testing.T) {
    75  			home := t.TempDir()
    76  			logger := log.NewNopLogger()
    77  			cfg, err := genutiltest.CreateDefaultCometConfig(home)
    78  			require.NoError(t, err)
    79  
    80  			appCodec := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}).Codec
    81  			err = genutiltest.ExecInitCmd(testMbm, home, appCodec)
    82  			require.NoError(t, err)
    83  
    84  			serverCtx := server.NewContext(viper.New(), cfg, logger)
    85  			clientCtx := client.Context{}.WithCodec(appCodec).WithHomeDir(home)
    86  
    87  			if tc.withKeyring {
    88  				path := hd.CreateHDPath(118, 0, 0).String()
    89  				kr, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, home, nil, appCodec)
    90  				require.NoError(t, err)
    91  				_, _, err = kr.NewMnemonic(tc.addr, keyring.English, path, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
    92  				require.NoError(t, err)
    93  				clientCtx = clientCtx.WithKeyring(kr)
    94  			}
    95  
    96  			ctx := context.Background()
    97  			ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
    98  			ctx = context.WithValue(ctx, server.ServerContextKey, serverCtx)
    99  
   100  			cmd := genutilcli.AddGenesisAccountCmd(home, addresscodec.NewBech32Codec("cosmos"))
   101  			cmd.SetArgs([]string{
   102  				tc.addr,
   103  				tc.denom,
   104  				fmt.Sprintf("--%s=home", flags.FlagHome),
   105  			})
   106  
   107  			if tc.expectErr {
   108  				require.Error(t, cmd.ExecuteContext(ctx))
   109  			} else {
   110  				require.NoError(t, cmd.ExecuteContext(ctx))
   111  			}
   112  		})
   113  	}
   114  }
   115  
   116  func TestBulkAddGenesisAccountCmd(t *testing.T) {
   117  	_, _, addr1 := testdata.KeyTestPubAddr()
   118  	_, _, addr2 := testdata.KeyTestPubAddr()
   119  	_, _, addr3 := testdata.KeyTestPubAddr()
   120  	addr1Str := addr1.String()
   121  	addr2Str := addr2.String()
   122  	addr3Str := addr3.String()
   123  
   124  	tests := []struct {
   125  		name       string
   126  		state      [][]genutil.GenesisAccount
   127  		expected   map[string]sdk.Coins
   128  		appendFlag bool
   129  		expectErr  bool
   130  	}{
   131  		{
   132  			name: "invalid address",
   133  			state: [][]genutil.GenesisAccount{
   134  				{
   135  					{
   136  						Address: "invalid",
   137  						Coins:   sdk.NewCoins(sdk.NewInt64Coin("test", 1)),
   138  					},
   139  				},
   140  			},
   141  			expectErr: true,
   142  		},
   143  		{
   144  			name: "no append flag for multiple account adds",
   145  			state: [][]genutil.GenesisAccount{
   146  				{
   147  					{
   148  						Address: addr1Str,
   149  						Coins:   sdk.NewCoins(sdk.NewInt64Coin("test", 1)),
   150  					},
   151  				},
   152  				{
   153  					{
   154  						Address: addr1Str,
   155  						Coins:   sdk.NewCoins(sdk.NewInt64Coin("test", 2)),
   156  					},
   157  				},
   158  			},
   159  			appendFlag: false,
   160  			expectErr:  true,
   161  		},
   162  
   163  		{
   164  			name: "multiple additions with append",
   165  			state: [][]genutil.GenesisAccount{
   166  				{
   167  					{
   168  						Address: addr1Str,
   169  						Coins:   sdk.NewCoins(sdk.NewInt64Coin("test", 1)),
   170  					},
   171  					{
   172  						Address: addr2Str,
   173  						Coins:   sdk.NewCoins(sdk.NewInt64Coin("test", 1)),
   174  					},
   175  				},
   176  				{
   177  					{
   178  						Address: addr1Str,
   179  						Coins:   sdk.NewCoins(sdk.NewInt64Coin("test", 2)),
   180  					},
   181  					{
   182  						Address: addr2Str,
   183  						Coins:   sdk.NewCoins(sdk.NewInt64Coin("stake", 1)),
   184  					},
   185  					{
   186  						Address: addr3Str,
   187  						Coins:   sdk.NewCoins(sdk.NewInt64Coin("test", 1)),
   188  					},
   189  				},
   190  			},
   191  			expected: map[string]sdk.Coins{
   192  				addr1Str: sdk.NewCoins(sdk.NewInt64Coin("test", 3)),
   193  				addr2Str: sdk.NewCoins(sdk.NewInt64Coin("test", 1), sdk.NewInt64Coin("stake", 1)),
   194  				addr3Str: sdk.NewCoins(sdk.NewInt64Coin("test", 1)),
   195  			},
   196  			appendFlag: true,
   197  			expectErr:  false,
   198  		},
   199  	}
   200  
   201  	for _, tc := range tests {
   202  		tc := tc
   203  		t.Run(tc.name, func(t *testing.T) {
   204  			home := t.TempDir()
   205  			logger := log.NewNopLogger()
   206  			cfg, err := genutiltest.CreateDefaultCometConfig(home)
   207  			require.NoError(t, err)
   208  
   209  			appCodec := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}).Codec
   210  			err = genutiltest.ExecInitCmd(testMbm, home, appCodec)
   211  			require.NoError(t, err)
   212  
   213  			serverCtx := server.NewContext(viper.New(), cfg, logger)
   214  			clientCtx := client.Context{}.WithCodec(appCodec).WithHomeDir(home)
   215  
   216  			ctx := context.Background()
   217  			ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx)
   218  			ctx = context.WithValue(ctx, server.ServerContextKey, serverCtx)
   219  
   220  			// The first iteration (pre-append) may not error.
   221  			// Check if any errors after all state transitions to genesis.
   222  			doesErr := false
   223  
   224  			// apply multiple state iterations if applicable (e.g. --append)
   225  			for _, state := range tc.state {
   226  				bz, err := json.Marshal(state)
   227  				require.NoError(t, err)
   228  
   229  				filePath := path.Join(home, "accounts.json")
   230  				err = os.WriteFile(filePath, bz, 0o600)
   231  				require.NoError(t, err)
   232  
   233  				cmd := genutilcli.AddBulkGenesisAccountCmd(home, addresscodec.NewBech32Codec("cosmos"))
   234  				args := []string{filePath}
   235  				if tc.appendFlag {
   236  					args = append(args, "--append")
   237  				}
   238  				cmd.SetArgs(args)
   239  
   240  				err = cmd.ExecuteContext(ctx)
   241  				if err != nil {
   242  					doesErr = true
   243  				}
   244  			}
   245  			require.Equal(t, tc.expectErr, doesErr)
   246  
   247  			// an error already occurred, no need to check the state
   248  			if doesErr {
   249  				return
   250  			}
   251  
   252  			appState, _, err := genutiltypes.GenesisStateFromGenFile(path.Join(home, "config", "genesis.json"))
   253  			require.NoError(t, err)
   254  
   255  			bankState := banktypes.GetGenesisStateFromAppState(appCodec, appState)
   256  
   257  			require.EqualValues(t, len(tc.expected), len(bankState.Balances))
   258  			for _, acc := range bankState.Balances {
   259  				require.True(t, tc.expected[acc.Address].Equal(acc.Coins), "expected: %v, got: %v", tc.expected[acc.Address], acc.Coins)
   260  			}
   261  
   262  			expectedSupply := sdk.NewCoins()
   263  			for _, coins := range tc.expected {
   264  				expectedSupply = expectedSupply.Add(coins...)
   265  			}
   266  			require.Equal(t, expectedSupply, bankState.Supply)
   267  		})
   268  	}
   269  }