package health import ( "context" "errors" "fmt" "net/http" "net/http/httptest" "testing" ) // TestReturns200IfThereAreNoChecks ensures that the result code of the health // endpoint is 200 if there are not currently registered checks. func TestReturns200IfThereAreNoChecks(t *testing.T) { recorder := httptest.NewRecorder() req, err := http.NewRequest(http.MethodGet, "https://fakeurl.com/debug/health", nil) if err != nil { t.Errorf("Failed to create request.") } StatusHandler(recorder, req) if recorder.Code != 200 { t.Errorf("Did not get a 200.") } } // TestReturns503IfThereAreErrorChecks ensures that the result code of the // health endpoint is 503 if there are health checks with errors. func TestReturns503IfThereAreErrorChecks(t *testing.T) { recorder := httptest.NewRecorder() req, err := http.NewRequest(http.MethodGet, "https://fakeurl.com/debug/health", nil) if err != nil { t.Errorf("Failed to create request.") } // Create a manual error Register("some_check", CheckFunc(func(context.Context) error { return errors.New("This Check did not succeed") })) StatusHandler(recorder, req) if recorder.Code != 503 { t.Errorf("Did not get a 503.") } } // TestHealthHandler ensures that our handler implementation correct protects // the web application when things aren't so healthy. func TestHealthHandler(t *testing.T) { // clear out existing checks. DefaultRegistry = NewRegistry() // protect an http server handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNoContent) })) // wrap it in our health handler handler = Handler(handler) // use this swap check status updater := NewStatusUpdater() Register("test_check", updater) // now, create a test server server := httptest.NewServer(handler) checkUp := func(t *testing.T, message string) { resp, err := http.Get(server.URL) if err != nil { t.Fatalf("error getting success status: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusNoContent { t.Fatalf("unexpected response code from server when %s: %d != %d", message, resp.StatusCode, http.StatusNoContent) } // NOTE(stevvooe): we really don't care about the body -- the format is // not standardized or supported, yet. } checkDown := func(t *testing.T, message string) { resp, err := http.Get(server.URL) if err != nil { t.Fatalf("error getting down status: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusServiceUnavailable { t.Fatalf("unexpected response code from server when %s: %d != %d", message, resp.StatusCode, http.StatusServiceUnavailable) } } // server should be up checkUp(t, "initial health check") // now, we fail the health check updater.Update(fmt.Errorf("the server is now out of commission")) checkDown(t, "server should be down") // should be down // bring server back up updater.Update(nil) checkUp(t, "when server is back up") // now we should be back up. }