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.
clair/vendor/github.com/coreos/pkg/health/health_test.go

199 lines
4.1 KiB

package health
import (
"encoding/json"
"errors"
"net/http"
"net/http/httptest"
"testing"
"github.com/coreos/pkg/httputil"
)
type boolChecker bool
func (b boolChecker) Healthy() error {
if b {
return nil
}
return errors.New("Unhealthy")
}
func errString(err error) string {
if err == nil {
return ""
}
return err.Error()
}
func TestCheck(t *testing.T) {
for i, test := range []struct {
checks []Checkable
expected string
}{
{[]Checkable{}, ""},
{[]Checkable{boolChecker(true)}, ""},
{[]Checkable{boolChecker(true), boolChecker(true)}, ""},
{[]Checkable{boolChecker(true), boolChecker(false)}, "Unhealthy"},
{[]Checkable{boolChecker(true), boolChecker(false), boolChecker(false)}, "multiple health check failure: [Unhealthy Unhealthy]"},
} {
err := Check(test.checks)
if errString(err) != test.expected {
t.Errorf("case %d: want %v, got %v", i, test.expected, errString(err))
}
}
}
func TestHandlerFunc(t *testing.T) {
for i, test := range []struct {
checker Checker
method string
expectedStatus string
expectedCode int
expectedMessage string
}{
{
Checker{
Checks: []Checkable{
boolChecker(true),
},
},
"GET",
"ok",
http.StatusOK,
"",
},
// Wrong method.
{
Checker{
Checks: []Checkable{
boolChecker(true),
},
},
"POST",
"",
http.StatusMethodNotAllowed,
"GET only acceptable method",
},
// Health check fails.
{
Checker{
Checks: []Checkable{
boolChecker(false),
},
},
"GET",
"error",
http.StatusInternalServerError,
"Unhealthy",
},
// Health check fails, with overridden ErrorHandler.
{
Checker{
Checks: []Checkable{
boolChecker(false),
},
UnhealthyHandler: func(w http.ResponseWriter, r *http.Request, err error) {
httputil.WriteJSONResponse(w,
http.StatusInternalServerError, StatusResponse{
Status: "error",
Details: &StatusResponseDetails{
Code: http.StatusInternalServerError,
Message: "Override!",
},
})
},
},
"GET",
"error",
http.StatusInternalServerError,
"Override!",
},
// Health check succeeds, with overridden SuccessHandler.
{
Checker{
Checks: []Checkable{
boolChecker(true),
},
HealthyHandler: func(w http.ResponseWriter, r *http.Request) {
httputil.WriteJSONResponse(w,
http.StatusOK, StatusResponse{
Status: "okey-dokey",
})
},
},
"GET",
"okey-dokey",
http.StatusOK,
"",
},
} {
w := httptest.NewRecorder()
r := &http.Request{}
r.Method = test.method
test.checker.ServeHTTP(w, r)
if w.Code != test.expectedCode {
t.Errorf("case %d: w.code == %v, want %v", i, w.Code, test.expectedCode)
}
if test.expectedStatus == "" {
// This is to handle the wrong-method case, when the
// body of the response is empty.
continue
}
statusMap := make(map[string]interface{})
err := json.Unmarshal(w.Body.Bytes(), &statusMap)
if err != nil {
t.Fatalf("case %d: failed to Unmarshal response body: %v", i, err)
}
status, ok := statusMap["status"].(string)
if !ok {
t.Errorf("case %d: status not present or not a string in json: %q", i, w.Body.Bytes())
}
if status != test.expectedStatus {
t.Errorf("case %d: status == %v, want %v", i, status, test.expectedStatus)
}
detailMap, ok := statusMap["details"].(map[string]interface{})
if test.expectedMessage != "" {
if !ok {
t.Fatalf("case %d: could not find/unmarshal detailMap", i)
}
message, ok := detailMap["message"].(string)
if !ok {
t.Fatalf("case %d: message not present or not a string in json: %q",
i, w.Body.Bytes())
}
if message != test.expectedMessage {
t.Errorf("case %d: message == %v, want %v", i, message, test.expectedMessage)
}
code, ok := detailMap["code"].(float64)
if !ok {
t.Fatalf("case %d: code not present or not an int in json: %q",
i, w.Body.Bytes())
}
if int(code) != test.expectedCode {
t.Errorf("case %d: code == %v, want %v", i, code, test.expectedCode)
}
} else {
if ok {
t.Errorf("case %d: unwanted detailMap present: %q", i, detailMap)
}
}
}
}