ratelimit_test.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package ratelimit
  2. import (
  3. "sync"
  4. "testing"
  5. "time"
  6. . "github.com/onsi/ginkgo"
  7. . "github.com/onsi/gomega"
  8. )
  9. var _ = Describe("RateLimiter", func() {
  10. It("should accurately rate-limit at small rates", func() {
  11. var count int
  12. rl := New(10, time.Minute)
  13. for !rl.Limit() {
  14. count++
  15. }
  16. Expect(count).To(Equal(10))
  17. })
  18. It("should accurately rate-limit at large rates", func() {
  19. var count int
  20. rl := New(100000, time.Hour)
  21. for !rl.Limit() {
  22. count++
  23. }
  24. Expect(count).To(BeNumerically("~", 100000, 10))
  25. })
  26. It("should accurately rate-limit at large intervals", func() {
  27. var count int
  28. rl := New(100, 360*24*time.Hour)
  29. for !rl.Limit() {
  30. count++
  31. }
  32. Expect(count).To(Equal(100))
  33. })
  34. It("should correctly increase allowance", func() {
  35. n := 25
  36. rl := New(n, 50*time.Millisecond)
  37. for i := 0; i < n; i++ {
  38. Expect(rl.Limit()).To(BeFalse(), "on cycle %d", i)
  39. }
  40. Expect(rl.Limit()).To(BeTrue())
  41. Eventually(rl.Limit, "60ms", "10ms").Should(BeFalse())
  42. })
  43. It("should correctly spread allowance", func() {
  44. var count int
  45. rl := New(5, 10*time.Millisecond)
  46. start := time.Now()
  47. for time.Since(start) < 100*time.Millisecond {
  48. if !rl.Limit() {
  49. count++
  50. }
  51. }
  52. Expect(count).To(BeNumerically("~", 54, 1))
  53. })
  54. It("should undo", func() {
  55. rl := New(5, time.Minute)
  56. Expect(rl.Limit()).To(BeFalse())
  57. Expect(rl.Limit()).To(BeFalse())
  58. Expect(rl.Limit()).To(BeFalse())
  59. Expect(rl.Limit()).To(BeFalse())
  60. Expect(rl.Limit()).To(BeFalse())
  61. Expect(rl.Limit()).To(BeTrue())
  62. rl.Undo()
  63. Expect(rl.Limit()).To(BeFalse())
  64. Expect(rl.Limit()).To(BeTrue())
  65. })
  66. It("should be thread-safe", func() {
  67. c := 100
  68. n := 100
  69. wg := sync.WaitGroup{}
  70. rl := New(c*n, time.Hour)
  71. for i := 0; i < c; i++ {
  72. wg.Add(1)
  73. go func(thread int) {
  74. defer GinkgoRecover()
  75. defer wg.Done()
  76. for j := 0; j < n; j++ {
  77. Expect(rl.Limit()).To(BeFalse(), "thread %d, cycle %d", thread, j)
  78. }
  79. }(i)
  80. }
  81. wg.Wait()
  82. Expect(rl.Limit()).To(BeTrue())
  83. })
  84. It("should allow to upate rate", func() {
  85. var count int
  86. rl := New(5, 50*time.Millisecond)
  87. for !rl.Limit() {
  88. count++
  89. }
  90. Expect(count).To(Equal(5))
  91. rl.UpdateRate(10)
  92. time.Sleep(50 * time.Millisecond)
  93. for !rl.Limit() {
  94. count++
  95. }
  96. Expect(count).To(Equal(15))
  97. })
  98. })
  99. // --------------------------------------------------------------------
  100. func BenchmarkLimit(b *testing.B) {
  101. rl := New(1000, time.Second)
  102. b.ResetTimer()
  103. for i := 0; i < b.N; i++ {
  104. rl.Limit()
  105. }
  106. }
  107. // --------------------------------------------------------------------
  108. func TestGinkgoSuite(t *testing.T) {
  109. RegisterFailHandler(Fail)
  110. RunSpecs(t, "github.com/bsm/ratelimit")
  111. }