github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/health/health_test.go (about) 1 package health 2 3 import ( 4 "context" 5 "encoding/json" 6 "errors" 7 "net/http" 8 "net/http/httptest" 9 "testing" 10 "time" 11 12 "github.com/stretchr/testify/assert" 13 "github.com/stretchr/testify/require" 14 ) 15 16 const ( 17 checkErr = "failed during RabbitMQ health check" 18 ) 19 20 func TestRegisterWithNoName(t *testing.T) { 21 h, err := New() 22 require.NoError(t, err) 23 24 err = h.Register(Config{ 25 Name: "", 26 Check: func(context.Context) error { 27 return nil 28 }, 29 }) 30 require.Error(t, err, "health check registration with empty name should return an error") 31 } 32 33 func TestDoubleRegister(t *testing.T) { 34 h, err := New() 35 require.NoError(t, err) 36 37 healthCheckName := "health-check" 38 39 conf := Config{ 40 Name: healthCheckName, 41 Check: func(context.Context) error { 42 return nil 43 }, 44 } 45 46 err = h.Register(conf) 47 require.NoError(t, err, "the first registration of a health check should not return an error, but got one") 48 49 err = h.Register(conf) 50 assert.Error(t, err, "the second registration of a health check config should return an error, but did not") 51 52 err = h.Register(Config{ 53 Name: healthCheckName, 54 Check: func(context.Context) error { 55 return errors.New("health checks registered") 56 }, 57 }) 58 assert.Error(t, err, "registration with same name, but different details should still return an error, but did not") 59 } 60 61 func TestHealthHandler(t *testing.T) { 62 h, err := New() 63 require.NoError(t, err) 64 65 res := httptest.NewRecorder() 66 req, err := http.NewRequest("GET", "http://localhost/status", nil) 67 require.NoError(t, err) 68 69 err = h.Register(Config{ 70 Name: "rabbitmq", 71 SkipOnErr: true, 72 Check: func(context.Context) error { return errors.New(checkErr) }, 73 }) 74 require.NoError(t, err) 75 76 err = h.Register(Config{ 77 Name: "mongodb", 78 Check: func(context.Context) error { return nil }, 79 }) 80 require.NoError(t, err) 81 82 err = h.Register(Config{ 83 Name: "snail-service", 84 SkipOnErr: true, 85 Timeout: time.Second * 1, 86 Check: func(context.Context) error { 87 time.Sleep(time.Second * 2) 88 return nil 89 }, 90 }) 91 require.NoError(t, err) 92 93 handler := h.Handler() 94 handler.ServeHTTP(res, req) 95 96 assert.Equal(t, http.StatusOK, res.Code, "status handler returned wrong status code") 97 98 body := make(map[string]interface{}) 99 err = json.NewDecoder(res.Body).Decode(&body) 100 require.NoError(t, err) 101 102 assert.Equal(t, string(StatusPartiallyAvailable), body["status"], "body returned wrong status") 103 104 failure, ok := body["failures"] 105 assert.True(t, ok, "body returned nil failures field") 106 107 f, ok := failure.(map[string]interface{}) 108 assert.True(t, ok, "body returned nil failures.rabbitmq field") 109 110 assert.Equal(t, checkErr, f["rabbitmq"], "body returned wrong status for rabbitmq") 111 assert.Equal(t, string(StatusTimeout), f["snail-service"], "body returned wrong status for snail-service") 112 } 113 114 func TestHealth_Measure(t *testing.T) { 115 h, err := New(WithChecks(Config{ 116 Name: "check1", 117 Timeout: time.Second, 118 SkipOnErr: false, 119 Check: func(context.Context) error { 120 time.Sleep(time.Second * 10) 121 return errors.New("check1") 122 }, 123 }, Config{ 124 Name: "check2", 125 Timeout: time.Second * 2, 126 SkipOnErr: false, 127 Check: func(context.Context) error { 128 time.Sleep(time.Second * 10) 129 return errors.New("check2") 130 }, 131 }), WithMaxConcurrent(2)) 132 require.NoError(t, err) 133 134 startedAt := time.Now() 135 result := h.Measure(context.Background()) 136 elapsed := time.Since(startedAt) 137 138 // both checks should run concurrently and should fail with timeout, 139 // so should take not less than 2 sec, but less than 5 that is sequential check time 140 require.GreaterOrEqual(t, elapsed.Milliseconds(), (time.Second * 2).Milliseconds()) 141 require.Less(t, elapsed.Milliseconds(), (time.Second * 5).Milliseconds()) 142 143 assert.Equal(t, StatusUnavailable, result.Status) 144 assert.Equal(t, string(StatusTimeout), result.Failures["check1"]) 145 assert.Equal(t, string(StatusTimeout), result.Failures["check2"]) 146 assert.Nil(t, result.System) 147 148 h, err = New(WithSystemInfo()) 149 require.NoError(t, err) 150 result = h.Measure(context.Background()) 151 152 assert.NotNil(t, result.System) 153 }