package generate import ( "bytes" "io" "math/rand" "os" "path/filepath" "strconv" "sync" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "github.com/nspcc-dev/neo-go/cli/input" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/spf13/viper" "github.com/stretchr/testify/require" "golang.org/x/term" ) func TestGenerateAlphabet(t *testing.T) { const size = 4 walletDir := t.TempDir() buf := setupTestTerminal(t) cmd := GenerateAlphabetCmd v := viper.GetViper() t.Run("zero size", func(t *testing.T) { buf.Reset() v.Set(commonflags.AlphabetWalletsFlag, walletDir) require.NoError(t, cmd.Flags().Set(commonflags.AlphabetSizeFlag, "0")) buf.WriteString("pass\r") require.Error(t, AlphabetCreds(cmd, nil)) }) t.Run("no password provided", func(t *testing.T) { buf.Reset() v.Set(commonflags.AlphabetWalletsFlag, walletDir) require.NoError(t, cmd.Flags().Set(commonflags.AlphabetSizeFlag, "1")) require.Error(t, AlphabetCreds(cmd, nil)) }) t.Run("missing directory", func(t *testing.T) { buf.Reset() dir := filepath.Join(os.TempDir(), "notexist."+strconv.FormatUint(rand.Uint64(), 10)) v.Set(commonflags.AlphabetWalletsFlag, dir) require.NoError(t, cmd.Flags().Set(commonflags.AlphabetSizeFlag, "1")) buf.WriteString("pass\r") require.Error(t, AlphabetCreds(cmd, nil)) }) t.Run("no password for contract group wallet", func(t *testing.T) { buf.Reset() v.Set(commonflags.AlphabetWalletsFlag, walletDir) require.NoError(t, cmd.Flags().Set(commonflags.AlphabetSizeFlag, strconv.FormatUint(size, 10))) for i := uint64(0); i < size; i++ { buf.WriteString(strconv.FormatUint(i, 10) + "\r") } require.Error(t, AlphabetCreds(cmd, nil)) }) buf.Reset() v.Set(commonflags.AlphabetWalletsFlag, walletDir) require.NoError(t, GenerateAlphabetCmd.Flags().Set(commonflags.AlphabetSizeFlag, strconv.FormatUint(size, 10))) for i := uint64(0); i < size; i++ { buf.WriteString(strconv.FormatUint(i, 10) + "\r") } buf.WriteString(constants.TestContractPassword + "\r") require.NoError(t, AlphabetCreds(GenerateAlphabetCmd, nil)) var wg sync.WaitGroup for i := uint64(0); i < size; i++ { i := i wg.Add(1) go func() { defer wg.Done() p := filepath.Join(walletDir, innerring.GlagoliticLetter(i).String()+".json") w, err := wallet.NewWalletFromFile(p) require.NoError(t, err, "wallet doesn't exist") require.Equal(t, 3, len(w.Accounts), "not all accounts were created") for _, a := range w.Accounts { err := a.Decrypt(strconv.FormatUint(i, 10), keys.NEP2ScryptParams()) require.NoError(t, err, "can't decrypt account") switch a.Label { case constants.ConsensusAccountName: require.Equal(t, smartcontract.GetDefaultHonestNodeCount(size), len(a.Contract.Parameters)) case constants.CommitteeAccountName: require.Equal(t, smartcontract.GetMajorityHonestNodeCount(size), len(a.Contract.Parameters)) default: require.Equal(t, constants.SingleAccountName, a.Label) } } }() } wg.Wait() t.Run("check contract group wallet", func(t *testing.T) { p := filepath.Join(walletDir, constants.ContractWalletFilename) w, err := wallet.NewWalletFromFile(p) require.NoError(t, err, "contract wallet doesn't exist") require.Equal(t, 1, len(w.Accounts), "contract wallet must have 1 accout") require.NoError(t, w.Accounts[0].Decrypt(constants.TestContractPassword, keys.NEP2ScryptParams())) }) } func setupTestTerminal(t *testing.T) *bytes.Buffer { in := bytes.NewBuffer(nil) input.Terminal = term.NewTerminal(input.ReadWriter{ Reader: in, Writer: io.Discard, }, "") t.Cleanup(func() { input.Terminal = nil }) return in }