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  }