github.com/klaytn/klaytn@v1.10.2/reward/staking_manager_test.go (about) 1 // Copyright 2019 The klaytn Authors 2 // This file is part of the klaytn library. 3 // 4 // The klaytn library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The klaytn library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>. 16 17 package reward 18 19 import ( 20 "encoding/json" 21 "testing" 22 23 "github.com/klaytn/klaytn/log" 24 "github.com/klaytn/klaytn/params" 25 "github.com/klaytn/klaytn/storage/database" 26 "github.com/stretchr/testify/assert" 27 ) 28 29 type testGovernance struct { 30 p *params.GovParamSet 31 } 32 33 func newTestGovernance(intMap map[int]interface{}) *testGovernance { 34 p, _ := params.NewGovParamSetIntMap(intMap) 35 return &testGovernance{p} 36 } 37 38 func newDefaultTestGovernance() *testGovernance { 39 return newTestGovernance(map[int]interface{}{ 40 params.Epoch: 604800, 41 params.Policy: params.WeightedRandom, 42 params.UnitPrice: 25000000000, 43 params.MintingAmount: "9600000000000000000", 44 params.Ratio: "34/54/12", 45 params.UseGiniCoeff: true, 46 params.DeferredTxFee: true, 47 params.MinimumStake: "5000000", 48 params.StakeUpdateInterval: 86400, 49 }) 50 } 51 52 type stakingManagerTestCase struct { 53 blockNum uint64 // Requested num in GetStakingInfo(num) 54 stakingNum uint64 // Corresponding staking info block number 55 stakingInfo *StakingInfo // Expected GetStakingInfo() output 56 } 57 58 // Note that Golang will correctly initialize these globals according to dependency. 59 // https://go.dev/ref/spec#Order_of_evaluation 60 61 // Note the testdata must not exceed maxStakingCache because otherwise cache test will fail. 62 var stakingManagerTestData = []*StakingInfo{ 63 stakingInfoTestCases[0].stakingInfo, 64 stakingInfoTestCases[1].stakingInfo, 65 stakingInfoTestCases[2].stakingInfo, 66 stakingInfoTestCases[3].stakingInfo, 67 } 68 var stakingManagerTestCases = generateStakingManagerTestCases() 69 70 func generateStakingManagerTestCases() []stakingManagerTestCase { 71 s := stakingManagerTestData 72 73 return []stakingManagerTestCase{ 74 {1, 0, s[0]}, 75 {100, 0, s[0]}, 76 {86400, 0, s[0]}, 77 {86401, 0, s[0]}, 78 {172800, 0, s[0]}, 79 {172801, 86400, s[1]}, 80 {200000, 86400, s[1]}, 81 {259200, 86400, s[1]}, 82 {259201, 172800, s[2]}, 83 {300000, 172800, s[2]}, 84 {345600, 172800, s[2]}, 85 {345601, 259200, s[3]}, 86 {400000, 259200, s[3]}, 87 } 88 } 89 90 func newStakingManagerForTest(t *testing.T) { 91 // test if nil 92 assert.Nil(t, GetStakingManager()) 93 assert.Nil(t, GetStakingInfo(123)) 94 95 st, err := updateStakingInfo(456) 96 assert.Nil(t, st) 97 assert.EqualError(t, err, ErrStakingManagerNotSet.Error()) 98 99 assert.EqualError(t, CheckStakingInfoStored(789), ErrStakingManagerNotSet.Error()) 100 101 // test if get same 102 stNew := NewStakingManager(newTestBlockChain(), newDefaultTestGovernance(), nil) 103 stGet := GetStakingManager() 104 assert.NotNil(t, stNew) 105 assert.Equal(t, stGet, stNew) 106 } 107 108 func resetStakingManagerForTest(t *testing.T) { 109 sm := GetStakingManager() 110 if sm == nil { 111 newStakingManagerForTest(t) 112 sm = GetStakingManager() 113 } 114 115 sm.stakingInfoCache = newStakingInfoCache() 116 sm.stakingInfoDB = database.NewMemoryDBManager() 117 } 118 119 func TestStakingManager_NewStakingManager(t *testing.T) { 120 newStakingManagerForTest(t) 121 } 122 123 // Check that appropriate StakingInfo is returned given various blockNum argument. 124 func checkGetStakingInfo(t *testing.T) { 125 for _, testcase := range stakingManagerTestCases { 126 expcectedInfo := testcase.stakingInfo 127 actualInfo := GetStakingInfo(testcase.blockNum) 128 129 assert.Equal(t, testcase.stakingNum, actualInfo.BlockNum) 130 assert.Equal(t, expcectedInfo, actualInfo) 131 } 132 } 133 134 // Check that StakinInfo are loaded from cache 135 func TestStakingManager_GetFromCache(t *testing.T) { 136 log.EnableLogForTest(log.LvlCrit, log.LvlDebug) 137 resetStakingManagerForTest(t) 138 139 for _, testdata := range stakingManagerTestData { 140 GetStakingManager().stakingInfoCache.add(testdata) 141 } 142 143 checkGetStakingInfo(t) 144 } 145 146 // Check that StakinInfo are loaded from database 147 func TestStakingManager_GetFromDB(t *testing.T) { 148 log.EnableLogForTest(log.LvlCrit, log.LvlDebug) 149 resetStakingManagerForTest(t) 150 151 for _, testdata := range stakingManagerTestData { 152 AddStakingInfoToDB(testdata) 153 } 154 155 checkGetStakingInfo(t) 156 } 157 158 // Even if Gini was -1 in the cache, GetStakingInfo returns valid Gini 159 func TestStakingManager_FillGiniFromCache(t *testing.T) { 160 log.EnableLogForTest(log.LvlCrit, log.LvlDebug) 161 resetStakingManagerForTest(t) 162 163 for _, testdata := range stakingManagerTestData { 164 // Insert a modified copy of testdata to cache 165 copydata := &StakingInfo{} 166 json.Unmarshal([]byte(testdata.String()), copydata) 167 copydata.Gini = -1 // Suppose Gini was -1 in the cache 168 GetStakingManager().stakingInfoCache.add(copydata) 169 } 170 171 checkGetStakingInfo(t) 172 } 173 174 // Even if Gini was -1 in the DB, GetStakingInfo returns valid Gini 175 func TestStakingManager_FillGiniFromDB(t *testing.T) { 176 log.EnableLogForTest(log.LvlCrit, log.LvlDebug) 177 resetStakingManagerForTest(t) 178 179 for _, testdata := range stakingManagerTestData { 180 // Insert a modified copy of testdata to cache 181 copydata := &StakingInfo{} 182 json.Unmarshal([]byte(testdata.String()), copydata) 183 copydata.Gini = -1 // Suppose Gini was -1 in the cache 184 AddStakingInfoToDB(copydata) 185 } 186 187 checkGetStakingInfo(t) 188 }