2018-11-15 12:54:45 +00:00
|
|
|
package prometheus
|
|
|
|
|
|
|
|
import (
|
2018-12-30 21:20:43 +00:00
|
|
|
"errors"
|
2022-04-18 20:42:07 +00:00
|
|
|
"io"
|
2018-12-30 21:20:43 +00:00
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"strings"
|
2018-11-15 12:54:45 +00:00
|
|
|
"testing"
|
2020-04-05 19:36:18 +00:00
|
|
|
"time"
|
2018-11-15 12:54:45 +00:00
|
|
|
|
2021-09-17 19:20:50 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/runtime"
|
2021-09-23 18:53:46 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/testing/assert"
|
|
|
|
"github.com/prysmaticlabs/prysm/testing/require"
|
2020-04-21 20:58:53 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
2018-11-15 12:54:45 +00:00
|
|
|
)
|
|
|
|
|
2020-04-21 20:58:53 +00:00
|
|
|
func init() {
|
|
|
|
logrus.SetLevel(logrus.DebugLevel)
|
2022-04-18 20:42:07 +00:00
|
|
|
logrus.SetOutput(io.Discard)
|
2020-04-21 20:58:53 +00:00
|
|
|
}
|
|
|
|
|
2018-11-15 12:54:45 +00:00
|
|
|
func TestLifecycle(t *testing.T) {
|
2021-02-12 17:45:22 +00:00
|
|
|
prometheusService := NewService(":2112", nil)
|
2018-11-15 12:54:45 +00:00
|
|
|
prometheusService.Start()
|
2020-04-05 19:36:18 +00:00
|
|
|
// Give service time to start.
|
|
|
|
time.Sleep(time.Second)
|
2018-11-15 12:54:45 +00:00
|
|
|
|
2020-04-05 19:36:18 +00:00
|
|
|
// Query the service to ensure it really started.
|
|
|
|
resp, err := http.Get("http://localhost:2112/metrics")
|
2020-08-25 10:18:29 +00:00
|
|
|
require.NoError(t, err)
|
2020-08-25 15:23:06 +00:00
|
|
|
assert.NotEqual(t, uint64(0), resp.ContentLength, "Unexpected content length 0")
|
2018-11-15 12:54:45 +00:00
|
|
|
|
2020-04-14 16:41:09 +00:00
|
|
|
err = prometheusService.Stop()
|
2020-08-25 10:18:29 +00:00
|
|
|
require.NoError(t, err)
|
2020-04-05 19:36:18 +00:00
|
|
|
// Give service time to stop.
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
|
|
|
|
// Query the service to ensure it really stopped.
|
|
|
|
_, err = http.Get("http://localhost:2112/metrics")
|
2020-08-25 15:23:06 +00:00
|
|
|
assert.NotNil(t, err, "Service still running after Stop()")
|
2018-11-15 12:54:45 +00:00
|
|
|
}
|
2018-12-30 21:20:43 +00:00
|
|
|
|
|
|
|
type mockService struct {
|
|
|
|
status error
|
|
|
|
}
|
|
|
|
|
2021-12-07 17:52:39 +00:00
|
|
|
func (_ *mockService) Start() {
|
2018-12-30 21:20:43 +00:00
|
|
|
}
|
|
|
|
|
2021-12-07 17:52:39 +00:00
|
|
|
func (_ *mockService) Stop() error {
|
2018-12-30 21:20:43 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *mockService) Status() error {
|
|
|
|
return m.status
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHealthz(t *testing.T) {
|
2021-09-17 19:20:50 +00:00
|
|
|
registry := runtime.NewServiceRegistry()
|
2018-12-30 21:20:43 +00:00
|
|
|
m := &mockService{}
|
2020-08-25 15:23:06 +00:00
|
|
|
require.NoError(t, registry.RegisterService(m), "Failed to register service")
|
2021-02-12 17:45:22 +00:00
|
|
|
s := NewService("" /*addr*/, registry)
|
2018-12-30 21:20:43 +00:00
|
|
|
|
|
|
|
req, err := http.NewRequest("GET", "/healthz", nil /*reader*/)
|
2020-08-25 10:18:29 +00:00
|
|
|
require.NoError(t, err)
|
2018-12-30 21:20:43 +00:00
|
|
|
|
|
|
|
handler := http.HandlerFunc(s.healthzHandler)
|
|
|
|
|
|
|
|
rr := httptest.NewRecorder()
|
|
|
|
handler.ServeHTTP(rr, req)
|
|
|
|
|
|
|
|
if status := rr.Code; status != http.StatusOK {
|
|
|
|
t.Errorf("expected OK status but got %v", rr.Code)
|
|
|
|
}
|
|
|
|
|
|
|
|
body := rr.Body.String()
|
|
|
|
if !strings.Contains(body, "*prometheus.mockService: OK") {
|
|
|
|
t.Errorf("Expected body to contain mockService status, but got %v", body)
|
|
|
|
}
|
|
|
|
|
|
|
|
m.status = errors.New("something really bad has happened")
|
|
|
|
|
|
|
|
rr = httptest.NewRecorder()
|
|
|
|
handler.ServeHTTP(rr, req)
|
|
|
|
|
2020-07-29 00:31:21 +00:00
|
|
|
if status := rr.Code; status != http.StatusServiceUnavailable {
|
|
|
|
t.Errorf("expected StatusServiceUnavailable status but got %v", rr.Code)
|
2018-12-30 21:20:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
body = rr.Body.String()
|
|
|
|
if !strings.Contains(
|
|
|
|
body,
|
2021-02-18 16:31:16 +00:00
|
|
|
"*prometheus.mockService: ERROR, something really bad has happened",
|
2018-12-30 21:20:43 +00:00
|
|
|
) {
|
|
|
|
t.Errorf("Expected body to contain mockService status, but got %v", body)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2019-01-24 01:26:25 +00:00
|
|
|
|
|
|
|
func TestStatus(t *testing.T) {
|
|
|
|
failError := errors.New("failure")
|
|
|
|
s := &Service{failStatus: failError}
|
|
|
|
|
|
|
|
if err := s.Status(); err != s.failStatus {
|
|
|
|
t.Errorf("Wanted: %v, got: %v", s.failStatus, s.Status())
|
|
|
|
}
|
|
|
|
}
|
2020-04-21 20:58:53 +00:00
|
|
|
|
|
|
|
func TestContentNegotiation(t *testing.T) {
|
|
|
|
t.Run("/healthz all services are ok", func(t *testing.T) {
|
2021-09-17 19:20:50 +00:00
|
|
|
registry := runtime.NewServiceRegistry()
|
2020-04-21 20:58:53 +00:00
|
|
|
m := &mockService{}
|
2020-08-25 15:23:06 +00:00
|
|
|
require.NoError(t, registry.RegisterService(m), "Failed to register service")
|
2021-02-12 17:45:22 +00:00
|
|
|
s := NewService("", registry)
|
2020-04-21 20:58:53 +00:00
|
|
|
|
|
|
|
req, err := http.NewRequest("GET", "/healthz", nil /* body */)
|
2020-08-25 10:18:29 +00:00
|
|
|
require.NoError(t, err)
|
2020-04-21 20:58:53 +00:00
|
|
|
|
|
|
|
handler := http.HandlerFunc(s.healthzHandler)
|
|
|
|
rr := httptest.NewRecorder()
|
|
|
|
handler.ServeHTTP(rr, req)
|
|
|
|
|
|
|
|
body := rr.Body.String()
|
|
|
|
if !strings.Contains(body, "*prometheus.mockService: OK") {
|
|
|
|
t.Errorf("Expected body to contain mockService status, but got %q", body)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Request response as JSON.
|
|
|
|
req.Header.Add("Accept", "application/json, */*;q=0.5")
|
|
|
|
rr = httptest.NewRecorder()
|
|
|
|
handler.ServeHTTP(rr, req)
|
|
|
|
|
|
|
|
body = rr.Body.String()
|
|
|
|
expectedJSON := "{\"error\":\"\",\"data\":[{\"service\":\"*prometheus.mockService\",\"status\":true,\"error\":\"\"}]}"
|
|
|
|
if !strings.Contains(body, expectedJSON) {
|
|
|
|
t.Errorf("Unexpected data, want: %q got %q", expectedJSON, body)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("/healthz failed service", func(t *testing.T) {
|
2021-09-17 19:20:50 +00:00
|
|
|
registry := runtime.NewServiceRegistry()
|
2020-04-21 20:58:53 +00:00
|
|
|
m := &mockService{}
|
|
|
|
m.status = errors.New("something is wrong")
|
2020-08-25 15:23:06 +00:00
|
|
|
require.NoError(t, registry.RegisterService(m), "Failed to register service")
|
2021-02-12 17:45:22 +00:00
|
|
|
s := NewService("", registry)
|
2020-04-21 20:58:53 +00:00
|
|
|
|
|
|
|
req, err := http.NewRequest("GET", "/healthz", nil /* body */)
|
2020-08-25 10:18:29 +00:00
|
|
|
require.NoError(t, err)
|
2020-04-21 20:58:53 +00:00
|
|
|
|
|
|
|
handler := http.HandlerFunc(s.healthzHandler)
|
|
|
|
rr := httptest.NewRecorder()
|
|
|
|
handler.ServeHTTP(rr, req)
|
|
|
|
|
|
|
|
body := rr.Body.String()
|
2021-02-18 16:31:16 +00:00
|
|
|
if !strings.Contains(body, "*prometheus.mockService: ERROR, something is wrong") {
|
2020-04-21 20:58:53 +00:00
|
|
|
t.Errorf("Expected body to contain mockService status, but got %q", body)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Request response as JSON.
|
|
|
|
req.Header.Add("Accept", "application/json, */*;q=0.5")
|
|
|
|
rr = httptest.NewRecorder()
|
|
|
|
handler.ServeHTTP(rr, req)
|
|
|
|
|
|
|
|
body = rr.Body.String()
|
|
|
|
expectedJSON := "{\"error\":\"\",\"data\":[{\"service\":\"*prometheus.mockService\",\"status\":false,\"error\":\"something is wrong\"}]}"
|
|
|
|
if !strings.Contains(body, expectedJSON) {
|
|
|
|
t.Errorf("Unexpected data, want: %q got %q", expectedJSON, body)
|
|
|
|
}
|
2020-07-29 00:31:21 +00:00
|
|
|
if rr.Code < 500 {
|
|
|
|
t.Errorf("Expected a server error response code, but got %d", rr.Code)
|
|
|
|
}
|
2020-04-21 20:58:53 +00:00
|
|
|
})
|
|
|
|
}
|