You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

fakelag_test.go 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Copyright (c) 2018 Shivaram Lingamneni <slingamn@cs.stanford.edu>
  2. // released under the MIT license
  3. package irc
  4. import (
  5. "testing"
  6. "time"
  7. )
  8. type mockTime struct {
  9. now time.Time
  10. sleepList []time.Duration
  11. lastCheckedSleep int
  12. }
  13. func (mt *mockTime) Now() (now time.Time) {
  14. return mt.now
  15. }
  16. func (mt *mockTime) Sleep(dur time.Duration) {
  17. mt.sleepList = append(mt.sleepList, dur)
  18. mt.pause(dur)
  19. }
  20. func (mt *mockTime) pause(dur time.Duration) {
  21. mt.now = mt.now.Add(dur)
  22. }
  23. func (mt *mockTime) lastSleep() (slept bool, duration time.Duration) {
  24. if mt.lastCheckedSleep == len(mt.sleepList)-1 {
  25. slept = false
  26. return
  27. }
  28. slept = true
  29. mt.lastCheckedSleep += 1
  30. duration = mt.sleepList[mt.lastCheckedSleep]
  31. return
  32. }
  33. func newFakelagForTesting(window time.Duration, burstLimit uint, throttleMessagesPerWindow uint, cooldown time.Duration) (*Fakelag, *mockTime) {
  34. fl := Fakelag{}
  35. fl.config = FakelagConfig{
  36. Enabled: true,
  37. Window: window,
  38. BurstLimit: burstLimit,
  39. MessagesPerWindow: throttleMessagesPerWindow,
  40. Cooldown: cooldown,
  41. }
  42. mt := new(mockTime)
  43. mt.now, _ = time.Parse("Mon Jan 2 15:04:05 -0700 MST 2006", "Mon Jan 2 15:04:05 -0700 MST 2006")
  44. mt.lastCheckedSleep = -1
  45. fl.nowFunc = mt.Now
  46. fl.sleepFunc = mt.Sleep
  47. return &fl, mt
  48. }
  49. func TestFakelag(t *testing.T) {
  50. window, _ := time.ParseDuration("1s")
  51. fl, mt := newFakelagForTesting(window, 3, 2, window)
  52. fl.Touch("")
  53. slept, _ := mt.lastSleep()
  54. if slept {
  55. t.Fatalf("should not have slept")
  56. }
  57. interval, _ := time.ParseDuration("100ms")
  58. for i := 0; i < 2; i++ {
  59. mt.pause(interval)
  60. fl.Touch("")
  61. slept, _ := mt.lastSleep()
  62. if slept {
  63. t.Fatalf("should not have slept")
  64. }
  65. }
  66. mt.pause(interval)
  67. fl.Touch("")
  68. if fl.state != FakelagThrottled {
  69. t.Fatalf("should be throttled")
  70. }
  71. slept, duration := mt.lastSleep()
  72. if !slept {
  73. t.Fatalf("should have slept due to fakelag")
  74. }
  75. expected, _ := time.ParseDuration("400ms")
  76. if duration != expected {
  77. t.Fatalf("incorrect sleep time: %v != %v", expected, duration)
  78. }
  79. // send another message without a pause; we should have to sleep for 500 msec
  80. fl.Touch("")
  81. if fl.state != FakelagThrottled {
  82. t.Fatalf("should be throttled")
  83. }
  84. slept, duration = mt.lastSleep()
  85. expected, _ = time.ParseDuration("500ms")
  86. if duration != expected {
  87. t.Fatalf("incorrect sleep time: %v != %v", duration, expected)
  88. }
  89. mt.pause(interval * 6)
  90. fl.Touch("")
  91. if fl.state != FakelagThrottled {
  92. t.Fatalf("should still be throttled")
  93. }
  94. slept, duration = mt.lastSleep()
  95. if duration != 0 {
  96. t.Fatalf("we paused for long enough that we shouldn't sleep here")
  97. }
  98. mt.pause(window * 2)
  99. fl.Touch("")
  100. if fl.state != FakelagBursting {
  101. t.Fatalf("should be bursting again")
  102. }
  103. slept, _ = mt.lastSleep()
  104. if slept {
  105. t.Fatalf("should not have slept")
  106. }
  107. }
  108. func TestSuspend(t *testing.T) {
  109. window, _ := time.ParseDuration("1s")
  110. fl, _ := newFakelagForTesting(window, 3, 2, window)
  111. assertEqual(fl.config.Enabled, true)
  112. // suspend idempotently disables
  113. fl.Suspend()
  114. assertEqual(fl.config.Enabled, false)
  115. fl.Suspend()
  116. assertEqual(fl.config.Enabled, false)
  117. // unsuspend idempotently enables
  118. fl.Unsuspend()
  119. assertEqual(fl.config.Enabled, true)
  120. fl.Unsuspend()
  121. assertEqual(fl.config.Enabled, true)
  122. fl.Suspend()
  123. assertEqual(fl.config.Enabled, false)
  124. fl2, _ := newFakelagForTesting(window, 3, 2, window)
  125. fl2.config.Enabled = false
  126. // if we were never enabled, suspend and unsuspend are both no-ops
  127. fl2.Suspend()
  128. assertEqual(fl2.config.Enabled, false)
  129. fl2.Suspend()
  130. assertEqual(fl2.config.Enabled, false)
  131. fl2.Unsuspend()
  132. assertEqual(fl2.config.Enabled, false)
  133. fl2.Unsuspend()
  134. assertEqual(fl2.config.Enabled, false)
  135. }