breaker_test.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package breaker
  2. import (
  3. "errors"
  4. "fmt"
  5. "strconv"
  6. "strings"
  7. "testing"
  8. "github.com/stretchr/testify/assert"
  9. "github.com/tal-tech/go-zero/core/stat"
  10. )
  11. func init() {
  12. stat.SetReporter(nil)
  13. }
  14. func TestCircuitBreaker_Allow(t *testing.T) {
  15. b := NewBreaker()
  16. assert.True(t, len(b.Name()) > 0)
  17. _, err := b.Allow()
  18. assert.Nil(t, err)
  19. }
  20. func TestLogReason(t *testing.T) {
  21. b := NewBreaker()
  22. assert.True(t, len(b.Name()) > 0)
  23. for i := 0; i < 1000; i++ {
  24. _ = b.Do(func() error {
  25. return errors.New(strconv.Itoa(i))
  26. })
  27. }
  28. errs := b.(*circuitBreaker).throttle.(loggedThrottle).errWin
  29. assert.Equal(t, numHistoryReasons, errs.count)
  30. }
  31. func TestErrorWindow(t *testing.T) {
  32. tests := []struct {
  33. name string
  34. reasons []string
  35. }{
  36. {
  37. name: "no error",
  38. },
  39. {
  40. name: "one error",
  41. reasons: []string{"foo"},
  42. },
  43. {
  44. name: "two errors",
  45. reasons: []string{"foo", "bar"},
  46. },
  47. {
  48. name: "five errors",
  49. reasons: []string{"first", "second", "third", "fourth", "fifth"},
  50. },
  51. {
  52. name: "six errors",
  53. reasons: []string{"first", "second", "third", "fourth", "fifth", "sixth"},
  54. },
  55. }
  56. for _, test := range tests {
  57. t.Run(test.name, func(t *testing.T) {
  58. var ew errorWindow
  59. for _, reason := range test.reasons {
  60. ew.add(reason)
  61. }
  62. var reasons []string
  63. if len(test.reasons) > numHistoryReasons {
  64. reasons = test.reasons[len(test.reasons)-numHistoryReasons:]
  65. } else {
  66. reasons = test.reasons
  67. }
  68. for _, reason := range reasons {
  69. assert.True(t, strings.Contains(ew.String(), reason), fmt.Sprintf("actual: %s", ew.String()))
  70. }
  71. })
  72. }
  73. }
  74. func TestPromiseWithReason(t *testing.T) {
  75. tests := []struct {
  76. name string
  77. reason string
  78. expect string
  79. }{
  80. {
  81. name: "success",
  82. },
  83. {
  84. name: "success",
  85. reason: "fail",
  86. expect: "fail",
  87. },
  88. }
  89. for _, test := range tests {
  90. t.Run(test.name, func(t *testing.T) {
  91. promise := promiseWithReason{
  92. promise: new(mockedPromise),
  93. errWin: new(errorWindow),
  94. }
  95. if len(test.reason) == 0 {
  96. promise.Accept()
  97. } else {
  98. promise.Reject(test.reason)
  99. }
  100. assert.True(t, strings.Contains(promise.errWin.String(), test.expect))
  101. })
  102. }
  103. }
  104. func BenchmarkGoogleBreaker(b *testing.B) {
  105. br := NewBreaker()
  106. for i := 0; i < b.N; i++ {
  107. _ = br.Do(func() error {
  108. return nil
  109. })
  110. }
  111. }
  112. type mockedPromise struct {
  113. }
  114. func (m *mockedPromise) Accept() {
  115. }
  116. func (m *mockedPromise) Reject() {
  117. }