engine_integration_test.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // +build integration
  2. package alerting
  3. import (
  4. "context"
  5. "errors"
  6. "net"
  7. "net/http"
  8. "net/http/httptest"
  9. "testing"
  10. "time"
  11. "github.com/grafana/grafana/pkg/setting"
  12. . "github.com/smartystreets/goconvey/convey"
  13. )
  14. func TestEngineTimeouts(t *testing.T) {
  15. Convey("Alerting engine timeout tests", t, func() {
  16. engine := NewEngine()
  17. setting.AlertingNotificationTimeout = 30 * time.Second
  18. setting.AlertingMaxAttempts = 3
  19. engine.resultHandler = &FakeResultHandler{}
  20. job := &Job{Running: true, Rule: &Rule{}}
  21. Convey("Should trigger as many retries as needed", func() {
  22. Convey("pended alert for datasource -> result handler should be worked", func() {
  23. // reduce alert timeout to test quickly
  24. setting.AlertingEvaluationTimeout = 30 * time.Second
  25. transportTimeoutInterval := 2 * time.Second
  26. serverBusySleepDuration := 1 * time.Second
  27. evalHandler := NewFakeCommonTimeoutHandler(transportTimeoutInterval, serverBusySleepDuration)
  28. resultHandler := NewFakeCommonTimeoutHandler(transportTimeoutInterval, serverBusySleepDuration)
  29. engine.evalHandler = evalHandler
  30. engine.resultHandler = resultHandler
  31. engine.processJobWithRetry(context.TODO(), job)
  32. So(evalHandler.EvalSucceed, ShouldEqual, true)
  33. So(resultHandler.ResultHandleSucceed, ShouldEqual, true)
  34. // initialize for other tests.
  35. setting.AlertingEvaluationTimeout = 2 * time.Second
  36. engine.resultHandler = &FakeResultHandler{}
  37. })
  38. })
  39. })
  40. }
  41. type FakeCommonTimeoutHandler struct {
  42. TransportTimeoutDuration time.Duration
  43. ServerBusySleepDuration time.Duration
  44. EvalSucceed bool
  45. ResultHandleSucceed bool
  46. }
  47. func NewFakeCommonTimeoutHandler(transportTimeoutDuration time.Duration, serverBusySleepDuration time.Duration) *FakeCommonTimeoutHandler {
  48. return &FakeCommonTimeoutHandler{
  49. TransportTimeoutDuration: transportTimeoutDuration,
  50. ServerBusySleepDuration: serverBusySleepDuration,
  51. EvalSucceed: false,
  52. ResultHandleSucceed: false,
  53. }
  54. }
  55. func (handler *FakeCommonTimeoutHandler) Eval(evalContext *EvalContext) {
  56. // 1. prepare mock server
  57. path := "/evaltimeout"
  58. srv := runBusyServer(path, handler.ServerBusySleepDuration)
  59. defer srv.Close()
  60. // 2. send requests
  61. url := srv.URL + path
  62. res, err := sendRequest(evalContext.Ctx, url, handler.TransportTimeoutDuration)
  63. if res != nil {
  64. defer res.Body.Close()
  65. }
  66. if err != nil {
  67. evalContext.Error = errors.New("Fake evaluation timeout test failure")
  68. return
  69. }
  70. if res.StatusCode == 200 {
  71. handler.EvalSucceed = true
  72. }
  73. evalContext.Error = errors.New("Fake evaluation timeout test failure; wrong response")
  74. }
  75. func (handler *FakeCommonTimeoutHandler) Handle(evalContext *EvalContext) error {
  76. // 1. prepare mock server
  77. path := "/resulthandle"
  78. srv := runBusyServer(path, handler.ServerBusySleepDuration)
  79. defer srv.Close()
  80. // 2. send requests
  81. url := srv.URL + path
  82. res, err := sendRequest(evalContext.Ctx, url, handler.TransportTimeoutDuration)
  83. if res != nil {
  84. defer res.Body.Close()
  85. }
  86. if err != nil {
  87. evalContext.Error = errors.New("Fake result handle timeout test failure")
  88. return evalContext.Error
  89. }
  90. if res.StatusCode == 200 {
  91. handler.ResultHandleSucceed = true
  92. return nil
  93. }
  94. evalContext.Error = errors.New("Fake result handle timeout test failure; wrong response")
  95. return evalContext.Error
  96. }
  97. func runBusyServer(path string, serverBusySleepDuration time.Duration) *httptest.Server {
  98. mux := http.NewServeMux()
  99. server := httptest.NewServer(mux)
  100. mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
  101. time.Sleep(serverBusySleepDuration)
  102. })
  103. return server
  104. }
  105. func sendRequest(context context.Context, url string, transportTimeoutInterval time.Duration) (resp *http.Response, err error) {
  106. req, err := http.NewRequest("GET", url, nil)
  107. if err != nil {
  108. return nil, err
  109. }
  110. req = req.WithContext(context)
  111. transport := http.Transport{
  112. Dial: (&net.Dialer{
  113. Timeout: transportTimeoutInterval,
  114. KeepAlive: transportTimeoutInterval,
  115. }).Dial,
  116. }
  117. client := http.Client{
  118. Transport: &transport,
  119. }
  120. return client.Do(req)
  121. }