github.com/prysmaticlabs/prysm@v1.4.4/shared/prometheus/service_test.go (about) 1 package prometheus 2 3 import ( 4 "errors" 5 "io/ioutil" 6 "net/http" 7 "net/http/httptest" 8 "strings" 9 "testing" 10 "time" 11 12 "github.com/prysmaticlabs/prysm/shared" 13 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 14 "github.com/prysmaticlabs/prysm/shared/testutil/require" 15 "github.com/sirupsen/logrus" 16 ) 17 18 func init() { 19 logrus.SetLevel(logrus.DebugLevel) 20 logrus.SetOutput(ioutil.Discard) 21 } 22 23 func TestLifecycle(t *testing.T) { 24 prometheusService := NewService(":2112", nil) 25 prometheusService.Start() 26 // Give service time to start. 27 time.Sleep(time.Second) 28 29 // Query the service to ensure it really started. 30 resp, err := http.Get("http://localhost:2112/metrics") 31 require.NoError(t, err) 32 assert.NotEqual(t, uint64(0), resp.ContentLength, "Unexpected content length 0") 33 34 err = prometheusService.Stop() 35 require.NoError(t, err) 36 // Give service time to stop. 37 time.Sleep(time.Second) 38 39 // Query the service to ensure it really stopped. 40 _, err = http.Get("http://localhost:2112/metrics") 41 assert.NotNil(t, err, "Service still running after Stop()") 42 } 43 44 type mockService struct { 45 status error 46 } 47 48 func (m *mockService) Start() { 49 } 50 51 func (m *mockService) Stop() error { 52 return nil 53 } 54 55 func (m *mockService) Status() error { 56 return m.status 57 } 58 59 func TestHealthz(t *testing.T) { 60 registry := shared.NewServiceRegistry() 61 m := &mockService{} 62 require.NoError(t, registry.RegisterService(m), "Failed to register service") 63 s := NewService("" /*addr*/, registry) 64 65 req, err := http.NewRequest("GET", "/healthz", nil /*reader*/) 66 require.NoError(t, err) 67 68 handler := http.HandlerFunc(s.healthzHandler) 69 70 rr := httptest.NewRecorder() 71 handler.ServeHTTP(rr, req) 72 73 if status := rr.Code; status != http.StatusOK { 74 t.Errorf("expected OK status but got %v", rr.Code) 75 } 76 77 body := rr.Body.String() 78 if !strings.Contains(body, "*prometheus.mockService: OK") { 79 t.Errorf("Expected body to contain mockService status, but got %v", body) 80 } 81 82 m.status = errors.New("something really bad has happened") 83 84 rr = httptest.NewRecorder() 85 handler.ServeHTTP(rr, req) 86 87 if status := rr.Code; status != http.StatusServiceUnavailable { 88 t.Errorf("expected StatusServiceUnavailable status but got %v", rr.Code) 89 } 90 91 body = rr.Body.String() 92 if !strings.Contains( 93 body, 94 "*prometheus.mockService: ERROR, something really bad has happened", 95 ) { 96 t.Errorf("Expected body to contain mockService status, but got %v", body) 97 } 98 99 } 100 101 func TestStatus(t *testing.T) { 102 failError := errors.New("failure") 103 s := &Service{failStatus: failError} 104 105 if err := s.Status(); err != s.failStatus { 106 t.Errorf("Wanted: %v, got: %v", s.failStatus, s.Status()) 107 } 108 } 109 110 func TestContentNegotiation(t *testing.T) { 111 t.Run("/healthz all services are ok", func(t *testing.T) { 112 registry := shared.NewServiceRegistry() 113 m := &mockService{} 114 require.NoError(t, registry.RegisterService(m), "Failed to register service") 115 s := NewService("", registry) 116 117 req, err := http.NewRequest("GET", "/healthz", nil /* body */) 118 require.NoError(t, err) 119 120 handler := http.HandlerFunc(s.healthzHandler) 121 rr := httptest.NewRecorder() 122 handler.ServeHTTP(rr, req) 123 124 body := rr.Body.String() 125 if !strings.Contains(body, "*prometheus.mockService: OK") { 126 t.Errorf("Expected body to contain mockService status, but got %q", body) 127 } 128 129 // Request response as JSON. 130 req.Header.Add("Accept", "application/json, */*;q=0.5") 131 rr = httptest.NewRecorder() 132 handler.ServeHTTP(rr, req) 133 134 body = rr.Body.String() 135 expectedJSON := "{\"error\":\"\",\"data\":[{\"service\":\"*prometheus.mockService\",\"status\":true,\"error\":\"\"}]}" 136 if !strings.Contains(body, expectedJSON) { 137 t.Errorf("Unexpected data, want: %q got %q", expectedJSON, body) 138 } 139 }) 140 141 t.Run("/healthz failed service", func(t *testing.T) { 142 registry := shared.NewServiceRegistry() 143 m := &mockService{} 144 m.status = errors.New("something is wrong") 145 require.NoError(t, registry.RegisterService(m), "Failed to register service") 146 s := NewService("", registry) 147 148 req, err := http.NewRequest("GET", "/healthz", nil /* body */) 149 require.NoError(t, err) 150 151 handler := http.HandlerFunc(s.healthzHandler) 152 rr := httptest.NewRecorder() 153 handler.ServeHTTP(rr, req) 154 155 body := rr.Body.String() 156 if !strings.Contains(body, "*prometheus.mockService: ERROR, something is wrong") { 157 t.Errorf("Expected body to contain mockService status, but got %q", body) 158 } 159 160 // Request response as JSON. 161 req.Header.Add("Accept", "application/json, */*;q=0.5") 162 rr = httptest.NewRecorder() 163 handler.ServeHTTP(rr, req) 164 165 body = rr.Body.String() 166 expectedJSON := "{\"error\":\"\",\"data\":[{\"service\":\"*prometheus.mockService\",\"status\":false,\"error\":\"something is wrong\"}]}" 167 if !strings.Contains(body, expectedJSON) { 168 t.Errorf("Unexpected data, want: %q got %q", expectedJSON, body) 169 } 170 if rr.Code < 500 { 171 t.Errorf("Expected a server error response code, but got %d", rr.Code) 172 } 173 }) 174 }