github.com/kaleido-io/go-ethereum@v1.9.7/les/balance_test.go (about) 1 // Copyright 2019 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package les 18 19 import ( 20 "testing" 21 "time" 22 23 "github.com/ethereum/go-ethereum/common/mclock" 24 ) 25 26 func TestSetBalance(t *testing.T) { 27 var clock = &mclock.Simulated{} 28 var inputs = []struct { 29 pos uint64 30 neg uint64 31 }{ 32 {1000, 0}, 33 {0, 1000}, 34 {1000, 1000}, 35 } 36 37 tracker := balanceTracker{} 38 tracker.init(clock, 1000) 39 defer tracker.stop(clock.Now()) 40 41 for _, i := range inputs { 42 tracker.setBalance(i.pos, i.neg) 43 pos, neg := tracker.getBalance(clock.Now()) 44 if pos != i.pos { 45 t.Fatalf("Positive balance mismatch, want %v, got %v", i.pos, pos) 46 } 47 if neg != i.neg { 48 t.Fatalf("Negative balance mismatch, want %v, got %v", i.neg, neg) 49 } 50 } 51 } 52 53 func TestBalanceTimeCost(t *testing.T) { 54 var ( 55 clock = &mclock.Simulated{} 56 tracker = balanceTracker{} 57 ) 58 tracker.init(clock, 1000) 59 defer tracker.stop(clock.Now()) 60 tracker.setFactors(false, 1, 1) 61 tracker.setFactors(true, 1, 1) 62 63 tracker.setBalance(uint64(time.Minute), 0) // 1 minute time allowance 64 65 var inputs = []struct { 66 runTime time.Duration 67 expPos uint64 68 expNeg uint64 69 }{ 70 {time.Second, uint64(time.Second * 59), 0}, 71 {0, uint64(time.Second * 59), 0}, 72 {time.Second * 59, 0, 0}, 73 {time.Second, 0, uint64(time.Second)}, 74 } 75 for _, i := range inputs { 76 clock.Run(i.runTime) 77 if pos, _ := tracker.getBalance(clock.Now()); pos != i.expPos { 78 t.Fatalf("Positive balance mismatch, want %v, got %v", i.expPos, pos) 79 } 80 if _, neg := tracker.getBalance(clock.Now()); neg != i.expNeg { 81 t.Fatalf("Negative balance mismatch, want %v, got %v", i.expNeg, neg) 82 } 83 } 84 85 tracker.setBalance(uint64(time.Minute), 0) // Refill 1 minute time allowance 86 for _, i := range inputs { 87 clock.Run(i.runTime) 88 if pos, _ := tracker.getBalance(clock.Now()); pos != i.expPos { 89 t.Fatalf("Positive balance mismatch, want %v, got %v", i.expPos, pos) 90 } 91 if _, neg := tracker.getBalance(clock.Now()); neg != i.expNeg { 92 t.Fatalf("Negative balance mismatch, want %v, got %v", i.expNeg, neg) 93 } 94 } 95 } 96 97 func TestBalanceReqCost(t *testing.T) { 98 var ( 99 clock = &mclock.Simulated{} 100 tracker = balanceTracker{} 101 ) 102 tracker.init(clock, 1000) 103 defer tracker.stop(clock.Now()) 104 tracker.setFactors(false, 1, 1) 105 tracker.setFactors(true, 1, 1) 106 107 tracker.setBalance(uint64(time.Minute), 0) // 1 minute time serving time allowance 108 var inputs = []struct { 109 reqCost uint64 110 expPos uint64 111 expNeg uint64 112 }{ 113 {uint64(time.Second), uint64(time.Second * 59), 0}, 114 {0, uint64(time.Second * 59), 0}, 115 {uint64(time.Second * 59), 0, 0}, 116 {uint64(time.Second), 0, uint64(time.Second)}, 117 } 118 for _, i := range inputs { 119 tracker.requestCost(i.reqCost) 120 if pos, _ := tracker.getBalance(clock.Now()); pos != i.expPos { 121 t.Fatalf("Positive balance mismatch, want %v, got %v", i.expPos, pos) 122 } 123 if _, neg := tracker.getBalance(clock.Now()); neg != i.expNeg { 124 t.Fatalf("Negative balance mismatch, want %v, got %v", i.expNeg, neg) 125 } 126 } 127 } 128 129 func TestBalanceToPriority(t *testing.T) { 130 var ( 131 clock = &mclock.Simulated{} 132 tracker = balanceTracker{} 133 ) 134 tracker.init(clock, 1000) // cap = 1000 135 defer tracker.stop(clock.Now()) 136 tracker.setFactors(false, 1, 1) 137 tracker.setFactors(true, 1, 1) 138 139 var inputs = []struct { 140 pos uint64 141 neg uint64 142 priority int64 143 }{ 144 {1000, 0, ^int64(1)}, 145 {2000, 0, ^int64(2)}, // Higher balance, lower priority value 146 {0, 0, 0}, 147 {0, 1000, 1000}, 148 } 149 for _, i := range inputs { 150 tracker.setBalance(i.pos, i.neg) 151 priority := tracker.getPriority(clock.Now()) 152 if priority != i.priority { 153 t.Fatalf("Priority mismatch, want %v, got %v", i.priority, priority) 154 } 155 } 156 } 157 158 func TestEstimatedPriority(t *testing.T) { 159 var ( 160 clock = &mclock.Simulated{} 161 tracker = balanceTracker{} 162 ) 163 tracker.init(clock, 1000000000) // cap = 1000,000,000 164 defer tracker.stop(clock.Now()) 165 tracker.setFactors(false, 1, 1) 166 tracker.setFactors(true, 1, 1) 167 168 tracker.setBalance(uint64(time.Minute), 0) 169 var inputs = []struct { 170 runTime time.Duration // time cost 171 futureTime time.Duration // diff of future time 172 reqCost uint64 // single request cost 173 priority int64 // expected estimated priority 174 }{ 175 {time.Second, time.Second, 0, ^int64(58)}, 176 {0, time.Second, 0, ^int64(58)}, 177 178 // 2 seconds time cost, 1 second estimated time cost, 10^9 request cost, 179 // 10^9 estimated request cost per second. 180 {time.Second, time.Second, 1000000000, ^int64(55)}, 181 182 // 3 seconds time cost, 3 second estimated time cost, 10^9*2 request cost, 183 // 4*10^9 estimated request cost. 184 {time.Second, 3 * time.Second, 1000000000, ^int64(48)}, 185 186 // All positive balance is used up 187 {time.Second * 55, 0, 0, 0}, 188 189 // 1 minute estimated time cost, 4/58 * 10^9 estimated request cost per sec. 190 {0, time.Minute, 0, int64(time.Minute) + int64(time.Second)*120/29}, 191 } 192 for _, i := range inputs { 193 clock.Run(i.runTime) 194 tracker.requestCost(i.reqCost) 195 priority := tracker.estimatedPriority(clock.Now()+mclock.AbsTime(i.futureTime), true) 196 if priority != i.priority { 197 t.Fatalf("Estimated priority mismatch, want %v, got %v", i.priority, priority) 198 } 199 } 200 } 201 202 func TestCallbackChecking(t *testing.T) { 203 var ( 204 clock = &mclock.Simulated{} 205 tracker = balanceTracker{} 206 ) 207 tracker.init(clock, 1000000) // cap = 1000,000 208 defer tracker.stop(clock.Now()) 209 tracker.setFactors(false, 1, 1) 210 tracker.setFactors(true, 1, 1) 211 212 var inputs = []struct { 213 priority int64 214 expDiff time.Duration 215 }{ 216 {^int64(500), time.Millisecond * 500}, 217 {0, time.Second}, 218 {int64(time.Second), 2 * time.Second}, 219 } 220 tracker.setBalance(uint64(time.Second), 0) 221 for _, i := range inputs { 222 diff, _ := tracker.timeUntil(i.priority) 223 if diff != i.expDiff { 224 t.Fatalf("Time difference mismatch, want %v, got %v", i.expDiff, diff) 225 } 226 } 227 } 228 229 func TestCallback(t *testing.T) { 230 var ( 231 clock = &mclock.Simulated{} 232 tracker = balanceTracker{} 233 ) 234 tracker.init(clock, 1000) // cap = 1000 235 defer tracker.stop(clock.Now()) 236 tracker.setFactors(false, 1, 1) 237 tracker.setFactors(true, 1, 1) 238 239 callCh := make(chan struct{}, 1) 240 tracker.setBalance(uint64(time.Minute), 0) 241 tracker.addCallback(balanceCallbackZero, 0, func() { callCh <- struct{}{} }) 242 243 clock.Run(time.Minute) 244 select { 245 case <-callCh: 246 case <-time.NewTimer(time.Second).C: 247 t.Fatalf("Callback hasn't been called yet") 248 } 249 250 tracker.setBalance(uint64(time.Minute), 0) 251 tracker.addCallback(balanceCallbackZero, 0, func() { callCh <- struct{}{} }) 252 tracker.removeCallback(balanceCallbackZero) 253 254 clock.Run(time.Minute) 255 select { 256 case <-callCh: 257 t.Fatalf("Callback shouldn't be called") 258 case <-time.NewTimer(time.Millisecond * 100).C: 259 } 260 }