github.com/iotexproject/iotex-core@v1.14.1-rc1/action/candidateregister_test.go (about)

     1  // Copyright (c) 2020 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package action
     7  
     8  import (
     9  	"encoding/hex"
    10  	"math/big"
    11  	"testing"
    12  
    13  	"github.com/pkg/errors"
    14  	"github.com/stretchr/testify/require"
    15  	"google.golang.org/protobuf/proto"
    16  
    17  	"github.com/iotexproject/go-pkgs/crypto"
    18  
    19  	"github.com/iotexproject/iotex-core/test/identityset"
    20  )
    21  
    22  var candidateRegisterTestParams = []struct {
    23  	SenderKey       crypto.PrivateKey
    24  	Nonce           uint64
    25  	Name            string
    26  	OperatorAddrStr string
    27  	RewardAddrStr   string
    28  	OwnerAddrStr    string
    29  	AmountStr       string
    30  	Duration        uint32
    31  	AutoStake       bool
    32  	Payload         []byte
    33  	GasLimit        uint64
    34  	GasPrice        *big.Int
    35  	Serialize       string
    36  	IntrinsicGas    uint64
    37  	Cost            string
    38  	ElpHash         string
    39  	Sign            string
    40  	SelpHash        string
    41  	Expected        error
    42  	SanityCheck     error
    43  }{
    44  	// valid test
    45  	{
    46  		identityset.PrivateKey(27), uint64(10), "test", "io10a298zmzvrt4guq79a9f4x7qedj59y7ery84he", "io13sj9mzpewn25ymheukte4v39hvjdtrfp00mlyv", "io19d0p3ah4g8ww9d7kcxfq87yxe7fnr8rpth5shj", "100", uint32(10000), false, []byte("payload"), uint64(1000000), big.NewInt(1000), "0a5c0a04746573741229696f3130613239387a6d7a7672743467757137396139663478377165646a35397937657279383468651a29696f3133736a396d7a7065776e3235796d6865756b74653476333968766a647472667030306d6c7976120331303018904e2a29696f313964307033616834673877773964376b63786671383779786537666e7238727074683573686a32077061796c6f6164", uint64(10700), "10700100", "769725930ed38023058bb4f01c220feef2e3e40febb36856dfb780c4f7b1ea9b", "0aaa01080118c0843d220431303030fa029a010a5c0a04746573741229696f3130613239387a6d7a7672743467757137396139663478377165646a35397937657279383468651a29696f3133736a396d7a7065776e3235796d6865756b74653476333968766a647472667030306d6c7976120331303018904e2a29696f313964307033616834673877773964376b63786671383779786537666e7238727074683573686a32077061796c6f6164124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a417819b5bcb635e3577acc8ca757f2c3d6afa451c2b6ff8a9179b141ac68e2c50305679e5d09d288da6f0fb52876a86c74deab6a5247edc6d371de5c2f121e159400", "35f53a536e014b32b85df50483ef04849b80ad60635b3b1979c5ba1096b65237", nil, nil,
    47  	},
    48  	// invalid test
    49  	{
    50  		identityset.PrivateKey(27), uint64(10), "test", "io10a298zmzvrt4guq79a9f4x7qedj59y7ery84he", "io13sj9mzpewn25ymheukte4v39hvjdtrfp00mlyv", "io19d0p3ah4g8ww9d7kcxfq87yxe7fnr8rpth5shj", "ab-10", uint32(10000), false, []byte("payload"), uint64(1000000), big.NewInt(1000), "", uint64(10700), "", "", "", "", ErrInvalidAmount, nil,
    51  	},
    52  	// invalid candidate name
    53  	{
    54  		identityset.PrivateKey(27), uint64(10), "F@¥", "io10a298zmzvrt4guq79a9f4x7qedj59y7ery84he", "io13sj9mzpewn25ymheukte4v39hvjdtrfp00mlyv", "io19d0p3ah4g8ww9d7kcxfq87yxe7fnr8rpth5shj", "10", uint32(10000), false, []byte("payload"), uint64(1000000), big.NewInt(1000), "", uint64(10700), "", "", "", "", nil, ErrInvalidCanName,
    55  	},
    56  	// invalid candidate name
    57  	{
    58  		identityset.PrivateKey(27), uint64(10), "", "io10a298zmzvrt4guq79a9f4x7qedj59y7ery84he", "io13sj9mzpewn25ymheukte4v39hvjdtrfp00mlyv", "io19d0p3ah4g8ww9d7kcxfq87yxe7fnr8rpth5shj", "10", uint32(10000), false, []byte("payload"), uint64(1000000), big.NewInt(1000), "", uint64(10700), "", "", "", "", nil, ErrInvalidCanName,
    59  	},
    60  	// invalid candidate name
    61  	{
    62  		identityset.PrivateKey(27), uint64(10), "aaaaaaaaaaaaa", "io10a298zmzvrt4guq79a9f4x7qedj59y7ery84he", "io13sj9mzpewn25ymheukte4v39hvjdtrfp00mlyv", "io19d0p3ah4g8ww9d7kcxfq87yxe7fnr8rpth5shj", "10", uint32(10000), false, []byte("payload"), uint64(1000000), big.NewInt(1000), "", uint64(10700), "", "", "", "", nil, ErrInvalidCanName,
    63  	},
    64  	{
    65  		identityset.PrivateKey(27), uint64(10), "test", "io10a298zmzvrt4guq79a9f4x7qedj59y7ery84he", "io13sj9mzpewn25ymheukte4v39hvjdtrfp00mlyv", "io19d0p3ah4g8ww9d7kcxfq87yxe7fnr8rpth5shj", "-10", uint32(10000), false, []byte("payload"), uint64(1000000), big.NewInt(1000), "", uint64(10700), "", "", "", "", nil, ErrInvalidAmount,
    66  	},
    67  	{
    68  		identityset.PrivateKey(27), uint64(10), "test", "io10a298zmzvrt4guq79a9f4x7qedj59y7ery84he", "io13sj9mzpewn25ymheukte4v39hvjdtrfp00mlyv", "io19d0p3ah4g8ww9d7kcxfq87yxe7fnr8rpth5shj", "100", uint32(10000), false, []byte("payload"), uint64(1000000), big.NewInt(-1000), "", uint64(10700), "", "", "", "", nil, ErrNegativeValue,
    69  	},
    70  }
    71  
    72  func TestCandidateRegister(t *testing.T) {
    73  	require := require.New(t)
    74  	for _, test := range candidateRegisterTestParams {
    75  		cr, err := NewCandidateRegister(test.Nonce, test.Name, test.OperatorAddrStr, test.RewardAddrStr, test.OwnerAddrStr, test.AmountStr, test.Duration, test.AutoStake, test.Payload, test.GasLimit, test.GasPrice)
    76  		require.Equal(test.Expected, errors.Cause(err))
    77  		if err != nil {
    78  			continue
    79  		}
    80  		err = cr.SanityCheck()
    81  		require.Equal(test.SanityCheck, errors.Cause(err))
    82  		if err != nil {
    83  			continue
    84  		}
    85  
    86  		require.Equal(test.Serialize, hex.EncodeToString(cr.Serialize()))
    87  
    88  		require.NoError(err)
    89  		require.Equal(test.GasLimit, cr.GasLimit())
    90  		require.Equal(test.GasPrice, cr.GasPrice())
    91  		require.Equal(test.Nonce, cr.Nonce())
    92  
    93  		require.Equal(test.Name, cr.Name())
    94  		require.Equal(test.OperatorAddrStr, cr.OperatorAddress().String())
    95  		require.Equal(test.RewardAddrStr, cr.RewardAddress().String())
    96  		require.Equal(test.OwnerAddrStr, cr.OwnerAddress().String())
    97  		require.Equal(test.AmountStr, cr.Amount().String())
    98  		require.Equal(test.Duration, cr.Duration())
    99  		require.Equal(test.AutoStake, cr.AutoStake())
   100  		require.Equal(test.Payload, cr.Payload())
   101  
   102  		gas, err := cr.IntrinsicGas()
   103  		require.NoError(err)
   104  		require.Equal(test.IntrinsicGas, gas)
   105  		cost, err := cr.Cost()
   106  		require.NoError(err)
   107  		require.Equal(test.Cost, cost.Text(10))
   108  
   109  		cr2 := &CandidateRegister{}
   110  		require.NoError(cr2.LoadProto(cr.Proto()))
   111  		require.Equal(test.Name, cr2.Name())
   112  		require.Equal(test.OperatorAddrStr, cr2.OperatorAddress().String())
   113  		require.Equal(test.RewardAddrStr, cr2.RewardAddress().String())
   114  		require.Equal(test.OwnerAddrStr, cr2.OwnerAddress().String())
   115  		require.Equal(test.AmountStr, cr2.Amount().String())
   116  		require.Equal(test.Duration, cr2.Duration())
   117  		require.Equal(test.AutoStake, cr2.AutoStake())
   118  		require.Equal(test.Payload, cr2.Payload())
   119  
   120  		// verify sign
   121  		bd := &EnvelopeBuilder{}
   122  		elp := bd.SetGasLimit(test.GasLimit).
   123  			SetGasPrice(test.GasPrice).
   124  			SetAction(cr).Build()
   125  		// sign
   126  		selp, err := Sign(elp, test.SenderKey)
   127  		require.NoError(err)
   128  		require.NotNil(selp)
   129  		ser, err := proto.Marshal(selp.Proto())
   130  		require.NoError(err)
   131  		require.Equal(test.Sign, hex.EncodeToString(ser))
   132  		hash, err := selp.Hash()
   133  		require.NoError(err)
   134  		require.Equal(test.SelpHash, hex.EncodeToString(hash[:]))
   135  		// verify signature
   136  		require.NoError(selp.VerifySignature())
   137  	}
   138  
   139  }
   140  
   141  func TestCandidateRegisterABIEncodeAndDecode(t *testing.T) {
   142  	require := require.New(t)
   143  	test := candidateRegisterTestParams[0]
   144  	stake, err := NewCandidateRegister(test.Nonce, test.Name, test.OperatorAddrStr, test.RewardAddrStr, test.OwnerAddrStr, test.AmountStr, test.Duration, test.AutoStake, test.Payload, test.GasLimit, test.GasPrice)
   145  	require.NoError(err)
   146  
   147  	data, err := stake.EncodeABIBinary()
   148  	require.NoError(err)
   149  	stake, err = NewCandidateRegisterFromABIBinary(data)
   150  	require.NoError(err)
   151  	require.Equal(test.Name, stake.Name())
   152  	require.Equal(test.OperatorAddrStr, stake.OperatorAddress().String())
   153  	require.Equal(test.RewardAddrStr, stake.RewardAddress().String())
   154  	require.Equal(test.OwnerAddrStr, stake.OwnerAddress().String())
   155  	require.Equal(test.AmountStr, stake.Amount().String())
   156  	require.Equal(test.Duration, stake.Duration())
   157  	require.Equal(test.AutoStake, stake.AutoStake())
   158  	require.Equal(test.Payload, stake.Payload())
   159  
   160  	stake.ownerAddress = nil
   161  	_, err = stake.EncodeABIBinary()
   162  	require.Equal(ErrAddress, err)
   163  	stake.rewardAddress = nil
   164  	_, err = stake.EncodeABIBinary()
   165  	require.Equal(ErrAddress, err)
   166  	stake.operatorAddress = nil
   167  	_, err = stake.EncodeABIBinary()
   168  	require.Equal(ErrAddress, err)
   169  }
   170  
   171  func TestIsValidCandidateName(t *testing.T) {
   172  	require := require.New(t)
   173  	tests := []struct {
   174  		input  string
   175  		output bool
   176  	}{
   177  		{
   178  			input:  "abc",
   179  			output: true,
   180  		},
   181  		{
   182  			input:  "123",
   183  			output: true,
   184  		},
   185  		{
   186  			input:  "abc123abc123",
   187  			output: true,
   188  		},
   189  		{
   190  			input:  "Abc123",
   191  			output: false,
   192  		},
   193  		{
   194  			input:  "Abc 123",
   195  			output: false,
   196  		},
   197  		{
   198  			input:  "Abc-123",
   199  			output: false,
   200  		},
   201  		{
   202  			input:  "abc123abc123abc123",
   203  			output: false,
   204  		},
   205  		{
   206  			input:  "",
   207  			output: false,
   208  		},
   209  	}
   210  
   211  	for _, tt := range tests {
   212  		output := IsValidCandidateName(tt.input)
   213  		require.Equal(tt.output, output)
   214  	}
   215  }