Adds health check and test

This commit is contained in:
Deepak Mallubhotla 2020-12-31 18:47:27 -06:00
parent 0e16bb5361
commit e77d3c4d5e
Signed by: deepak
GPG Key ID: 64BF53A3369104E7
5 changed files with 149 additions and 3 deletions

58
routes/health.go Normal file
View File

@ -0,0 +1,58 @@
package routes
import (
"encoding/json"
"gitea.deepak.science/deepak/gogmagog/models"
"github.com/go-chi/chi"
"net/http"
)
func newHealthRouter(m *models.Model) http.Handler {
router := chi.NewRouter()
router.Get("/", getHealthFunc(m))
return router
}
type healthCheck struct {
Name string `json:"name"`
Healthy bool `json:"healthy"`
Message string `json:"message"`
}
func getHealthFunc(m *models.Model) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var healths []*healthCheck
healths = append(healths, dbHealth(m))
code := http.StatusOK
for _, h := range healths {
if !h.Healthy {
code = http.StatusInternalServerError
break
}
}
w.WriteHeader(code)
w.Header().Add("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(healths); err != nil {
serverError(w, err)
}
}
}
func dbHealth(m *models.Model) *healthCheck {
errMessage := ""
health := true
name := "Store"
err := m.Healthy()
if err != nil {
errMessage = err.Error()
health = false
}
return &healthCheck{
Name: name,
Healthy: health,
Message: errMessage,
}
}

87
routes/health_test.go Normal file
View File

@ -0,0 +1,87 @@
package routes_test
import (
"fmt"
"gitea.deepak.science/deepak/gogmagog/routes"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"testing"
)
func TestEmptyHeatlhErrorWriter(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
router := routes.NewRouter(m)
req, _ := http.NewRequest("GET", "/health", nil)
rr := NewBadWriter()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
}
func TestEmptyHealth(t *testing.T) {
// set up
assert := assert.New(t)
m := getEmptyModel()
router := routes.NewRouter(m)
req, _ := http.NewRequest("GET", "/health", nil)
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusOK, status)
expected := `[
{
"name": "Store",
"healthy": true,
"message": ""
}
]`
assert.JSONEq(expected, rr.Body.String())
contentType := rr.Header().Get("Content-Type")
assert.Equal("application/json", contentType)
}
func TestUnhealthyDB(t *testing.T) {
// set up
assert := assert.New(t)
errorMsg := "error"
m := getErrorModel(errorMsg)
router := routes.NewRouter(m)
req, _ := http.NewRequest("GET", "/health", nil)
rr := httptest.NewRecorder()
// function under test
router.ServeHTTP(rr, req)
// check results
status := rr.Code
assert.Equal(http.StatusInternalServerError, status)
expected := fmt.Sprintf(`[
{
"name": "Store",
"healthy": false,
"message": "%s"
}
]`, errorMsg)
assert.JSONEq(expected, rr.Body.String())
contentType := rr.Header().Get("Content-Type")
assert.Equal("application/json", contentType)
}

View File

@ -66,7 +66,7 @@ func TestErrorPlan(t *testing.T) {
// set up
assert := assert.New(t)
m := getErrorModel()
m := getErrorModel("Model always errors")
router := routes.NewRouter(m)
req, _ := http.NewRequest("GET", "/plans", nil)

View File

@ -87,7 +87,7 @@ type errorStore struct {
error error
}
func getErrorModel() *models.Model {
e := &errorStore{error: fmt.Errorf("Model always errors")}
func getErrorModel(errorMsg string) *models.Model {
e := &errorStore{error: fmt.Errorf(errorMsg)}
return models.New(e)
}

View File

@ -13,6 +13,7 @@ func NewRouter(m *models.Model) http.Handler {
router.MethodNotAllowed(methodNotAllowedHandler)
router.NotFound(notFoundHandler)
router.Mount("/plans", newPlanRouter(m))
router.Mount("/health", newHealthRouter(m))
router.Get("/ping", ping)
return router
}