Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 

460 Zeilen
12 KiB

  1. // Copyright 2015 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // +build go1.7
  5. package rate
  6. import (
  7. "context"
  8. "math"
  9. "runtime"
  10. "sync"
  11. "sync/atomic"
  12. "testing"
  13. "time"
  14. )
  15. func TestLimit(t *testing.T) {
  16. if Limit(10) == Inf {
  17. t.Errorf("Limit(10) == Inf should be false")
  18. }
  19. }
  20. func closeEnough(a, b Limit) bool {
  21. return (math.Abs(float64(a)/float64(b)) - 1.0) < 1e-9
  22. }
  23. func TestEvery(t *testing.T) {
  24. cases := []struct {
  25. interval time.Duration
  26. lim Limit
  27. }{
  28. {0, Inf},
  29. {-1, Inf},
  30. {1 * time.Nanosecond, Limit(1e9)},
  31. {1 * time.Microsecond, Limit(1e6)},
  32. {1 * time.Millisecond, Limit(1e3)},
  33. {10 * time.Millisecond, Limit(100)},
  34. {100 * time.Millisecond, Limit(10)},
  35. {1 * time.Second, Limit(1)},
  36. {2 * time.Second, Limit(0.5)},
  37. {time.Duration(2.5 * float64(time.Second)), Limit(0.4)},
  38. {4 * time.Second, Limit(0.25)},
  39. {10 * time.Second, Limit(0.1)},
  40. {time.Duration(math.MaxInt64), Limit(1e9 / float64(math.MaxInt64))},
  41. }
  42. for _, tc := range cases {
  43. lim := Every(tc.interval)
  44. if !closeEnough(lim, tc.lim) {
  45. t.Errorf("Every(%v) = %v want %v", tc.interval, lim, tc.lim)
  46. }
  47. }
  48. }
  49. const (
  50. d = 100 * time.Millisecond
  51. )
  52. var (
  53. t0 = time.Now()
  54. t1 = t0.Add(time.Duration(1) * d)
  55. t2 = t0.Add(time.Duration(2) * d)
  56. t3 = t0.Add(time.Duration(3) * d)
  57. t4 = t0.Add(time.Duration(4) * d)
  58. t5 = t0.Add(time.Duration(5) * d)
  59. t9 = t0.Add(time.Duration(9) * d)
  60. )
  61. type allow struct {
  62. t time.Time
  63. n int
  64. ok bool
  65. }
  66. func run(t *testing.T, lim *Limiter, allows []allow) {
  67. for i, allow := range allows {
  68. ok := lim.AllowN(allow.t, allow.n)
  69. if ok != allow.ok {
  70. t.Errorf("step %d: lim.AllowN(%v, %v) = %v want %v",
  71. i, allow.t, allow.n, ok, allow.ok)
  72. }
  73. }
  74. }
  75. func TestLimiterBurst1(t *testing.T) {
  76. run(t, NewLimiter(10, 1), []allow{
  77. {t0, 1, true},
  78. {t0, 1, false},
  79. {t0, 1, false},
  80. {t1, 1, true},
  81. {t1, 1, false},
  82. {t1, 1, false},
  83. {t2, 2, false}, // burst size is 1, so n=2 always fails
  84. {t2, 1, true},
  85. {t2, 1, false},
  86. })
  87. }
  88. func TestLimiterBurst3(t *testing.T) {
  89. run(t, NewLimiter(10, 3), []allow{
  90. {t0, 2, true},
  91. {t0, 2, false},
  92. {t0, 1, true},
  93. {t0, 1, false},
  94. {t1, 4, false},
  95. {t2, 1, true},
  96. {t3, 1, true},
  97. {t4, 1, true},
  98. {t4, 1, true},
  99. {t4, 1, false},
  100. {t4, 1, false},
  101. {t9, 3, true},
  102. {t9, 0, true},
  103. })
  104. }
  105. func TestLimiterJumpBackwards(t *testing.T) {
  106. run(t, NewLimiter(10, 3), []allow{
  107. {t1, 1, true}, // start at t1
  108. {t0, 1, true}, // jump back to t0, two tokens remain
  109. {t0, 1, true},
  110. {t0, 1, false},
  111. {t0, 1, false},
  112. {t1, 1, true}, // got a token
  113. {t1, 1, false},
  114. {t1, 1, false},
  115. {t2, 1, true}, // got another token
  116. {t2, 1, false},
  117. {t2, 1, false},
  118. })
  119. }
  120. func TestSimultaneousRequests(t *testing.T) {
  121. const (
  122. limit = 1
  123. burst = 5
  124. numRequests = 15
  125. )
  126. var (
  127. wg sync.WaitGroup
  128. numOK = uint32(0)
  129. )
  130. // Very slow replenishing bucket.
  131. lim := NewLimiter(limit, burst)
  132. // Tries to take a token, atomically updates the counter and decreases the wait
  133. // group counter.
  134. f := func() {
  135. defer wg.Done()
  136. if ok := lim.Allow(); ok {
  137. atomic.AddUint32(&numOK, 1)
  138. }
  139. }
  140. wg.Add(numRequests)
  141. for i := 0; i < numRequests; i++ {
  142. go f()
  143. }
  144. wg.Wait()
  145. if numOK != burst {
  146. t.Errorf("numOK = %d, want %d", numOK, burst)
  147. }
  148. }
  149. func TestLongRunningQPS(t *testing.T) {
  150. if testing.Short() {
  151. t.Skip("skipping in short mode")
  152. }
  153. if runtime.GOOS == "openbsd" {
  154. t.Skip("low resolution time.Sleep invalidates test (golang.org/issue/14183)")
  155. return
  156. }
  157. // The test runs for a few seconds executing many requests and then checks
  158. // that overall number of requests is reasonable.
  159. const (
  160. limit = 100
  161. burst = 100
  162. )
  163. var numOK = int32(0)
  164. lim := NewLimiter(limit, burst)
  165. var wg sync.WaitGroup
  166. f := func() {
  167. if ok := lim.Allow(); ok {
  168. atomic.AddInt32(&numOK, 1)
  169. }
  170. wg.Done()
  171. }
  172. start := time.Now()
  173. end := start.Add(5 * time.Second)
  174. for time.Now().Before(end) {
  175. wg.Add(1)
  176. go f()
  177. // This will still offer ~500 requests per second, but won't consume
  178. // outrageous amount of CPU.
  179. time.Sleep(2 * time.Millisecond)
  180. }
  181. wg.Wait()
  182. elapsed := time.Since(start)
  183. ideal := burst + (limit * float64(elapsed) / float64(time.Second))
  184. // We should never get more requests than allowed.
  185. if want := int32(ideal + 1); numOK > want {
  186. t.Errorf("numOK = %d, want %d (ideal %f)", numOK, want, ideal)
  187. }
  188. // We should get very close to the number of requests allowed.
  189. if want := int32(0.999 * ideal); numOK < want {
  190. t.Errorf("numOK = %d, want %d (ideal %f)", numOK, want, ideal)
  191. }
  192. }
  193. type request struct {
  194. t time.Time
  195. n int
  196. act time.Time
  197. ok bool
  198. }
  199. // dFromDuration converts a duration to a multiple of the global constant d
  200. func dFromDuration(dur time.Duration) int {
  201. // Adding a millisecond to be swallowed by the integer division
  202. // because we don't care about small inaccuracies
  203. return int((dur + time.Millisecond) / d)
  204. }
  205. // dSince returns multiples of d since t0
  206. func dSince(t time.Time) int {
  207. return dFromDuration(t.Sub(t0))
  208. }
  209. func runReserve(t *testing.T, lim *Limiter, req request) *Reservation {
  210. return runReserveMax(t, lim, req, InfDuration)
  211. }
  212. func runReserveMax(t *testing.T, lim *Limiter, req request, maxReserve time.Duration) *Reservation {
  213. r := lim.reserveN(req.t, req.n, maxReserve)
  214. if r.ok && (dSince(r.timeToAct) != dSince(req.act)) || r.ok != req.ok {
  215. t.Errorf("lim.reserveN(t%d, %v, %v) = (t%d, %v) want (t%d, %v)",
  216. dSince(req.t), req.n, maxReserve, dSince(r.timeToAct), r.ok, dSince(req.act), req.ok)
  217. }
  218. return &r
  219. }
  220. func TestSimpleReserve(t *testing.T) {
  221. lim := NewLimiter(10, 2)
  222. runReserve(t, lim, request{t0, 2, t0, true})
  223. runReserve(t, lim, request{t0, 2, t2, true})
  224. runReserve(t, lim, request{t3, 2, t4, true})
  225. }
  226. func TestMix(t *testing.T) {
  227. lim := NewLimiter(10, 2)
  228. runReserve(t, lim, request{t0, 3, t1, false}) // should return false because n > Burst
  229. runReserve(t, lim, request{t0, 2, t0, true})
  230. run(t, lim, []allow{{t1, 2, false}}) // not enought tokens - don't allow
  231. runReserve(t, lim, request{t1, 2, t2, true})
  232. run(t, lim, []allow{{t1, 1, false}}) // negative tokens - don't allow
  233. run(t, lim, []allow{{t3, 1, true}})
  234. }
  235. func TestCancelInvalid(t *testing.T) {
  236. lim := NewLimiter(10, 2)
  237. runReserve(t, lim, request{t0, 2, t0, true})
  238. r := runReserve(t, lim, request{t0, 3, t3, false})
  239. r.CancelAt(t0) // should have no effect
  240. runReserve(t, lim, request{t0, 2, t2, true}) // did not get extra tokens
  241. }
  242. func TestCancelLast(t *testing.T) {
  243. lim := NewLimiter(10, 2)
  244. runReserve(t, lim, request{t0, 2, t0, true})
  245. r := runReserve(t, lim, request{t0, 2, t2, true})
  246. r.CancelAt(t1) // got 2 tokens back
  247. runReserve(t, lim, request{t1, 2, t2, true})
  248. }
  249. func TestCancelTooLate(t *testing.T) {
  250. lim := NewLimiter(10, 2)
  251. runReserve(t, lim, request{t0, 2, t0, true})
  252. r := runReserve(t, lim, request{t0, 2, t2, true})
  253. r.CancelAt(t3) // too late to cancel - should have no effect
  254. runReserve(t, lim, request{t3, 2, t4, true})
  255. }
  256. func TestCancel0Tokens(t *testing.T) {
  257. lim := NewLimiter(10, 2)
  258. runReserve(t, lim, request{t0, 2, t0, true})
  259. r := runReserve(t, lim, request{t0, 1, t1, true})
  260. runReserve(t, lim, request{t0, 1, t2, true})
  261. r.CancelAt(t0) // got 0 tokens back
  262. runReserve(t, lim, request{t0, 1, t3, true})
  263. }
  264. func TestCancel1Token(t *testing.T) {
  265. lim := NewLimiter(10, 2)
  266. runReserve(t, lim, request{t0, 2, t0, true})
  267. r := runReserve(t, lim, request{t0, 2, t2, true})
  268. runReserve(t, lim, request{t0, 1, t3, true})
  269. r.CancelAt(t2) // got 1 token back
  270. runReserve(t, lim, request{t2, 2, t4, true})
  271. }
  272. func TestCancelMulti(t *testing.T) {
  273. lim := NewLimiter(10, 4)
  274. runReserve(t, lim, request{t0, 4, t0, true})
  275. rA := runReserve(t, lim, request{t0, 3, t3, true})
  276. runReserve(t, lim, request{t0, 1, t4, true})
  277. rC := runReserve(t, lim, request{t0, 1, t5, true})
  278. rC.CancelAt(t1) // get 1 token back
  279. rA.CancelAt(t1) // get 2 tokens back, as if C was never reserved
  280. runReserve(t, lim, request{t1, 3, t5, true})
  281. }
  282. func TestReserveJumpBack(t *testing.T) {
  283. lim := NewLimiter(10, 2)
  284. runReserve(t, lim, request{t1, 2, t1, true}) // start at t1
  285. runReserve(t, lim, request{t0, 1, t1, true}) // should violate Limit,Burst
  286. runReserve(t, lim, request{t2, 2, t3, true})
  287. }
  288. func TestReserveJumpBackCancel(t *testing.T) {
  289. lim := NewLimiter(10, 2)
  290. runReserve(t, lim, request{t1, 2, t1, true}) // start at t1
  291. r := runReserve(t, lim, request{t1, 2, t3, true})
  292. runReserve(t, lim, request{t1, 1, t4, true})
  293. r.CancelAt(t0) // cancel at t0, get 1 token back
  294. runReserve(t, lim, request{t1, 2, t4, true}) // should violate Limit,Burst
  295. }
  296. func TestReserveSetLimit(t *testing.T) {
  297. lim := NewLimiter(5, 2)
  298. runReserve(t, lim, request{t0, 2, t0, true})
  299. runReserve(t, lim, request{t0, 2, t4, true})
  300. lim.SetLimitAt(t2, 10)
  301. runReserve(t, lim, request{t2, 1, t4, true}) // violates Limit and Burst
  302. }
  303. func TestReserveSetLimitCancel(t *testing.T) {
  304. lim := NewLimiter(5, 2)
  305. runReserve(t, lim, request{t0, 2, t0, true})
  306. r := runReserve(t, lim, request{t0, 2, t4, true})
  307. lim.SetLimitAt(t2, 10)
  308. r.CancelAt(t2) // 2 tokens back
  309. runReserve(t, lim, request{t2, 2, t3, true})
  310. }
  311. func TestReserveMax(t *testing.T) {
  312. lim := NewLimiter(10, 2)
  313. maxT := d
  314. runReserveMax(t, lim, request{t0, 2, t0, true}, maxT)
  315. runReserveMax(t, lim, request{t0, 1, t1, true}, maxT) // reserve for close future
  316. runReserveMax(t, lim, request{t0, 1, t2, false}, maxT) // time to act too far in the future
  317. }
  318. type wait struct {
  319. name string
  320. ctx context.Context
  321. n int
  322. delay int // in multiples of d
  323. nilErr bool
  324. }
  325. func runWait(t *testing.T, lim *Limiter, w wait) {
  326. start := time.Now()
  327. err := lim.WaitN(w.ctx, w.n)
  328. delay := time.Now().Sub(start)
  329. if (w.nilErr && err != nil) || (!w.nilErr && err == nil) || w.delay != dFromDuration(delay) {
  330. errString := "<nil>"
  331. if !w.nilErr {
  332. errString = "<non-nil error>"
  333. }
  334. t.Errorf("lim.WaitN(%v, lim, %v) = %v with delay %v ; want %v with delay %v",
  335. w.name, w.n, err, delay, errString, d*time.Duration(w.delay))
  336. }
  337. }
  338. func TestWaitSimple(t *testing.T) {
  339. lim := NewLimiter(10, 3)
  340. ctx, cancel := context.WithCancel(context.Background())
  341. cancel()
  342. runWait(t, lim, wait{"already-cancelled", ctx, 1, 0, false})
  343. runWait(t, lim, wait{"exceed-burst-error", context.Background(), 4, 0, false})
  344. runWait(t, lim, wait{"act-now", context.Background(), 2, 0, true})
  345. runWait(t, lim, wait{"act-later", context.Background(), 3, 2, true})
  346. }
  347. func TestWaitCancel(t *testing.T) {
  348. lim := NewLimiter(10, 3)
  349. ctx, cancel := context.WithCancel(context.Background())
  350. runWait(t, lim, wait{"act-now", ctx, 2, 0, true}) // after this lim.tokens = 1
  351. go func() {
  352. time.Sleep(d)
  353. cancel()
  354. }()
  355. runWait(t, lim, wait{"will-cancel", ctx, 3, 1, false})
  356. // should get 3 tokens back, and have lim.tokens = 2
  357. t.Logf("tokens:%v last:%v lastEvent:%v", lim.tokens, lim.last, lim.lastEvent)
  358. runWait(t, lim, wait{"act-now-after-cancel", context.Background(), 2, 0, true})
  359. }
  360. func TestWaitTimeout(t *testing.T) {
  361. lim := NewLimiter(10, 3)
  362. ctx, cancel := context.WithTimeout(context.Background(), d)
  363. defer cancel()
  364. runWait(t, lim, wait{"act-now", ctx, 2, 0, true})
  365. runWait(t, lim, wait{"w-timeout-err", ctx, 3, 0, false})
  366. }
  367. func TestWaitInf(t *testing.T) {
  368. lim := NewLimiter(Inf, 0)
  369. runWait(t, lim, wait{"exceed-burst-no-error", context.Background(), 3, 0, true})
  370. }
  371. func BenchmarkAllowN(b *testing.B) {
  372. lim := NewLimiter(Every(1*time.Second), 1)
  373. now := time.Now()
  374. b.ReportAllocs()
  375. b.ResetTimer()
  376. b.RunParallel(func(pb *testing.PB) {
  377. for pb.Next() {
  378. lim.AllowN(now, 1)
  379. }
  380. })
  381. }
  382. func BenchmarkWaitNNoDelay(b *testing.B) {
  383. lim := NewLimiter(Limit(b.N), b.N)
  384. ctx := context.Background()
  385. b.ReportAllocs()
  386. b.ResetTimer()
  387. for i := 0; i < b.N; i++ {
  388. lim.WaitN(ctx, 1)
  389. }
  390. }