func TestUnmarhsalJSON(t *testing.T) { testcases := []struct { encoded []byte // encoded JSON status health.Status // expected object }{ {[]byte(`{"healthy":true}`), health.Healthy}, {[]byte(`{"healthy":true,"properties":{"message":"service is up"}}`), health.StatusHealthy("service is up")}, {[]byte(`{}`), health.StatusUnhealthy("", nil)}, {[]byte(`{"healthy":false,"properties":{"message":"service is down"}}`), health.StatusUnhealthy("service is down", nil)}, {[]byte(`{"healthy":false,"properties":{"cause":"network unreachable"}}`), health.StatusUnhealthy("", errors.New("network unreachable"))}, {[]byte(`{"healthy":false,"properties":{"message":"service is down","cause":"network unreachable"}}`), health.StatusUnhealthy("service is down", errors.New("network unreachable"))}, {[]byte(`{"healthy":true,"properties":{"message":"ok","size":3.0, "sync":true}}`), health.StatusHealthyWithProperties(map[string]interface{}{"message": "ok", "size": 3.0, "sync": true})}, {[]byte(`{"healthy":false,"properties":{"message":"ok","size":3.0, "sync":true}}`), health.StatusUnhealthyWithProperties(map[string]interface{}{"message": "ok", "size": 3.0, "sync": true})}, } for _, s := range testcases { decoded := &health.Status{} err := json.Unmarshal(s.encoded, decoded) assert.Nil(t, err) if err != nil { println(err.Error()) } assert.EqualValues(t, s.status, *decoded) } }
func TestHTTPHandlerReturnsAll(t *testing.T) { for name, fn := range published { health.RegisterFunc(name, fn) } handler := health.Handler() req, err := http.NewRequest("GET", "http://ignored.path.to.dontcare.example.com/", nil) assert.Nil(t, err) w := httptest.NewRecorder() handler(w, req) assert.Equal(t, health.HTTPStatusCodeHealthChecksFail, w.Code) var actual map[string]health.Status assert.Nil(t, json.Unmarshal(w.Body.Bytes(), &actual)) var expected = map[string]health.Status{ "pass": health.Healthy, "fail": health.StatusUnhealthy(FAILING, nil), "panic": health.StatusUnhealthy(health.CheckPanicked, errors.New("oops!")), } assert.Len(t, actual, len(expected)) assert.EqualValues(t, actual, expected) teardown() }
func TestMarhsalJSONUnhealthy(t *testing.T) { testcases := []health.Status{ health.StatusUnhealthy("", nil), health.StatusUnhealthy("service is down", nil), health.StatusUnhealthy("", errors.New("network unreachable")), health.StatusUnhealthy("service is down", errors.New("network unreachable")), health.StatusUnhealthyWithProperties(map[string]interface{}{"message": "ok", "size": 3.0, "sync": true}), } for _, s := range testcases { b, err := json.Marshal(s) assert.Nil(t, err) decoded := &health.Status{} err = json.Unmarshal(b, decoded) assert.Nil(t, err) if err != nil { println(err.Error()) } assert.EqualValues(t, s, *decoded) } }
func (hc *healthChecker) Check() health.Status { hc.mutex.Lock() defer hc.mutex.Unlock() now := time.Now() numDisconnected := 0 minDuration := time.Duration(0) for id, health := range hc.clients { wasConnected := health.connected health.connected = health.cl.isConnected() if !health.connected { if wasConnected { health.disconnectedTime = now } disconnectedDuration := now.Sub(health.disconnectedTime) if disconnectedDuration > hc.disconnectedThreshold { hc.logger.Warningf("Peer %v replication client disconnected for %v", id, disconnectedDuration) numDisconnected++ if numDisconnected == 1 || (minDuration > disconnectedDuration) { minDuration = disconnectedDuration } } } } if numDisconnected > 0 { message := fmt.Sprintf( "%d/%d replication clients disconnected for at least %v", numDisconnected, len(hc.clients), minDuration) return health.StatusUnhealthy(message, nil) } return health.Healthy }
func TestStatusCause(t *testing.T) { e := errors.New("invalid") uh := health.StatusUnhealthy("failed", e) assert.Equal(t, e.Error(), uh.Properties["cause"]) }
func TestStatusUnhealthy(t *testing.T) { uh := health.StatusUnhealthy("failed", nil) assert.False(t, uh.Healthy) }
func alwaysFailing() health.Status { return health.StatusUnhealthy(FAILING, errors.New("undefined failure")) }
func (stub *stubHealthCheck) Check() health.Status { if stub.healthy { return health.StatusHealthy("I'm a lumberjack and I'm OK") } return health.StatusUnhealthy(FAILING, nil) }
assert.Len(t, checks, 1) for _, hc := range checks { assert.False(t, hc.Healthy) assert.Equal(t, health.CheckPanicked, hc.Properties["message"]) assert.Equal(t, cause, hc.Properties["cause"]) } teardown() } //----------------------------------------------------------------------------- // publishing health checks var published = map[string]health.CheckerFunc{ "pass": func() health.Status { return health.Healthy }, "fail": func() health.Status { return health.StatusUnhealthy(FAILING, nil) }, "panic": func() health.Status { panic("oops!") }, } func TestHTTPHandlerSuccess(t *testing.T) { testCase := "pass" health.RegisterFunc(testCase, published[testCase]) handler := health.Handler() req, err := http.NewRequest("GET", "http://ignored.path.to.dontcare.example.com/", nil) assert.Nil(t, err) w := httptest.NewRecorder() handler(w, req) assert.Equal(t, health.HTTPStatusCodeHealthChecksPass, w.Code) teardown() }