github.com/iotexproject/iotex-core@v1.14.1-rc1/action/protocol/account/protocol_test.go (about) 1 // Copyright (c) 2019 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 account 7 8 import ( 9 "context" 10 "math/big" 11 "testing" 12 13 "github.com/golang/mock/gomock" 14 "github.com/iotexproject/iotex-address/address" 15 "github.com/stretchr/testify/require" 16 17 "github.com/iotexproject/iotex-core/action/protocol" 18 accountutil "github.com/iotexproject/iotex-core/action/protocol/account/util" 19 "github.com/iotexproject/iotex-core/action/protocol/rewarding" 20 "github.com/iotexproject/iotex-core/blockchain/genesis" 21 "github.com/iotexproject/iotex-core/db/batch" 22 "github.com/iotexproject/iotex-core/state" 23 "github.com/iotexproject/iotex-core/test/identityset" 24 "github.com/iotexproject/iotex-core/test/mock/mock_chainmanager" 25 ) 26 27 func TestLoadOrCreateAccountState(t *testing.T) { 28 require := require.New(t) 29 30 ctrl := gomock.NewController(t) 31 sm := mock_chainmanager.NewMockStateManager(ctrl) 32 cb := batch.NewCachedBatch() 33 sm.EXPECT().State(gomock.Any(), gomock.Any()).DoAndReturn( 34 func(account interface{}, opts ...protocol.StateOption) (uint64, error) { 35 cfg, err := protocol.CreateStateConfig(opts...) 36 if err != nil { 37 return 0, err 38 } 39 val, err := cb.Get("state", cfg.Key) 40 if err != nil { 41 return 0, state.ErrStateNotExist 42 } 43 return 0, state.Deserialize(account, val) 44 }).AnyTimes() 45 sm.EXPECT().PutState(gomock.Any(), gomock.Any()).DoAndReturn( 46 func(account interface{}, opts ...protocol.StateOption) (uint64, error) { 47 cfg, err := protocol.CreateStateConfig(opts...) 48 if err != nil { 49 return 0, err 50 } 51 ss, err := state.Serialize(account) 52 if err != nil { 53 return 0, err 54 } 55 cb.Put("state", cfg.Key, ss, "failed to put state") 56 return 0, nil 57 }).AnyTimes() 58 59 for _, test := range []struct { 60 accountType int32 61 addr address.Address 62 expectedNonce uint64 63 }{ 64 { 65 0, 66 identityset.Address(27), 67 uint64(0x1), 68 }, 69 { 70 1, 71 identityset.Address(28), 72 uint64(0x0), 73 }, 74 } { 75 var ( 76 s *state.Account 77 err error 78 ) 79 if test.accountType == 0 { 80 s, err = accountutil.LoadAccount(sm, test.addr, state.LegacyNonceAccountTypeOption()) 81 } else { 82 s, err = accountutil.LoadAccount(sm, test.addr) 83 } 84 require.NoError(err) 85 require.Equal(big.NewInt(0), s.Balance) 86 require.Equal(test.accountType, s.AccountType()) 87 require.Equal(test.expectedNonce, s.PendingNonce()) 88 89 if test.accountType == 0 { 90 require.NoError(createAccount(sm, test.addr.String(), big.NewInt(5), state.LegacyNonceAccountTypeOption())) 91 s, err = accountutil.LoadAccount(sm, test.addr, state.LegacyNonceAccountTypeOption()) 92 } else { 93 require.NoError(createAccount(sm, test.addr.String(), big.NewInt(5))) 94 s, err = accountutil.LoadAccount(sm, test.addr) 95 } 96 require.NoError(err) 97 require.Equal("5", s.Balance.String()) 98 require.Equal(test.accountType, s.AccountType()) 99 require.Equal(test.expectedNonce, s.PendingNonce()) 100 } 101 } 102 103 func TestProtocol_Initialize(t *testing.T) { 104 require := require.New(t) 105 ctrl := gomock.NewController(t) 106 sm := mock_chainmanager.NewMockStateManager(ctrl) 107 cb := batch.NewCachedBatch() 108 sm.EXPECT().State(gomock.Any(), gomock.Any()).DoAndReturn( 109 func(account interface{}, opts ...protocol.StateOption) (uint64, error) { 110 cfg, err := protocol.CreateStateConfig(opts...) 111 if err != nil { 112 return 0, err 113 } 114 val, err := cb.Get("state", cfg.Key) 115 if err != nil { 116 return 0, state.ErrStateNotExist 117 } 118 return 0, state.Deserialize(account, val) 119 }).AnyTimes() 120 sm.EXPECT().PutState(gomock.Any(), gomock.Any()).DoAndReturn( 121 func(account interface{}, opts ...protocol.StateOption) (uint64, error) { 122 cfg, err := protocol.CreateStateConfig(opts...) 123 if err != nil { 124 return 0, err 125 } 126 ss, err := state.Serialize(account) 127 if err != nil { 128 return 0, err 129 } 130 cb.Put("state", cfg.Key, ss, "failed to put state") 131 return 0, nil 132 }).AnyTimes() 133 134 ge := genesis.Default 135 ge.Account.InitBalanceMap = map[string]string{ 136 identityset.Address(0).String(): "100", 137 } 138 ctx := protocol.WithBlockCtx(context.Background(), protocol.BlockCtx{ 139 BlockHeight: 0, 140 }) 141 ctx = protocol.WithFeatureCtx(genesis.WithGenesisContext(ctx, ge)) 142 p := NewProtocol(rewarding.DepositGas) 143 require.NoError( 144 p.CreateGenesisStates( 145 ctx, 146 sm, 147 ), 148 ) 149 150 ge.Account.InitBalanceMap[identityset.Address(1).String()] = "-1" 151 require.Error( 152 p.CreateGenesisStates( 153 ctx, 154 sm, 155 ), 156 ) 157 158 require.Error(createAccount(sm, identityset.Address(0).String(), big.NewInt(0))) 159 acc0, err := accountutil.LoadAccount(sm, identityset.Address(0)) 160 require.NoError(err) 161 require.Equal(big.NewInt(100), acc0.Balance) 162 } 163 164 func TestRegisterOrForceRegister(t *testing.T) { 165 require := require.New(t) 166 167 p := NewProtocol(rewarding.DepositGas) 168 require.Equal(protocolID, p.Name()) 169 170 registry := protocol.NewRegistry() 171 require.NoError(p.Register(registry)) 172 require.Error(p.Register(registry)) 173 require.NoError(p.ForceRegister(registry)) 174 175 foundP := FindProtocol(registry) 176 require.Equal(p, foundP) 177 178 require.Nil(FindProtocol(nil)) 179 180 registry = protocol.NewRegistry() 181 require.Nil(FindProtocol(registry)) 182 } 183 184 // TestAssertZeroBlockHeight tests the assertZeroBlockHeight funcs 185 func TestAssertZeroBlockHeight(t *testing.T) { 186 require := require.New(t) 187 188 p := NewProtocol(rewarding.DepositGas) 189 require.NoError(p.assertZeroBlockHeight(0)) 190 // should return an error if height is not zero 191 require.Error(p.assertZeroBlockHeight(1)) 192 } 193 194 func TestAssertAmountsAndEqualLength(t *testing.T) { 195 require := require.New(t) 196 197 p := NewProtocol(rewarding.DepositGas) 198 amounts := []*big.Int{ 199 big.NewInt(0), 200 big.NewInt(1), 201 big.NewInt(2), 202 } 203 require.NoError(p.assertAmounts(amounts)) 204 amounts[0] = big.NewInt(-1) 205 require.Error(p.assertAmounts(amounts)) 206 207 addrs := []address.Address{ 208 &address.AddrV1{}, 209 &address.AddrV1{}, 210 &address.AddrV1{}, 211 } 212 require.NoError(p.assertEqualLength(addrs, amounts)) 213 addrs = addrs[:2] 214 require.Error(p.assertEqualLength(addrs, amounts)) 215 }