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 }