balance_test.go 7.2 KB

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