143 lines
3.4 KiB
Go
143 lines
3.4 KiB
Go
package internalhttp
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func newTestConfig() Config {
|
|
return Config{
|
|
Addr: ":0",
|
|
ReadHeaderTimeout: time.Second,
|
|
ReadTimeout: time.Second,
|
|
WriteTimeout: time.Second,
|
|
IdleTimeout: time.Second,
|
|
}
|
|
}
|
|
|
|
type stubReadiness struct {
|
|
err error
|
|
}
|
|
|
|
func (probe stubReadiness) Check(_ context.Context) error {
|
|
return probe.err
|
|
}
|
|
|
|
func newTestServer(t *testing.T, deps Dependencies) http.Handler {
|
|
t.Helper()
|
|
server, err := NewServer(newTestConfig(), deps)
|
|
require.NoError(t, err)
|
|
return server.handler
|
|
}
|
|
|
|
func TestHealthzReturnsOK(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
handler := newTestServer(t, Dependencies{})
|
|
|
|
rec := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, HealthzPath, nil)
|
|
handler.ServeHTTP(rec, req)
|
|
|
|
require.Equal(t, http.StatusOK, rec.Code)
|
|
require.Equal(t, jsonContentType, rec.Header().Get("Content-Type"))
|
|
|
|
var body statusResponse
|
|
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body))
|
|
require.Equal(t, "ok", body.Status)
|
|
}
|
|
|
|
func TestReadyzReturnsReadyWhenProbeIsNil(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
handler := newTestServer(t, Dependencies{})
|
|
|
|
rec := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, ReadyzPath, nil)
|
|
handler.ServeHTTP(rec, req)
|
|
|
|
require.Equal(t, http.StatusOK, rec.Code)
|
|
|
|
var body statusResponse
|
|
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body))
|
|
require.Equal(t, "ready", body.Status)
|
|
}
|
|
|
|
func TestReadyzReturnsReadyWhenProbeSucceeds(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
handler := newTestServer(t, Dependencies{Readiness: stubReadiness{}})
|
|
|
|
rec := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, ReadyzPath, nil)
|
|
handler.ServeHTTP(rec, req)
|
|
|
|
require.Equal(t, http.StatusOK, rec.Code)
|
|
|
|
var body statusResponse
|
|
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body))
|
|
require.Equal(t, "ready", body.Status)
|
|
}
|
|
|
|
func TestReadyzReturnsServiceUnavailableWhenProbeFails(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
handler := newTestServer(t, Dependencies{
|
|
Readiness: stubReadiness{err: errors.New("postgres ping: connection refused")},
|
|
})
|
|
|
|
rec := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, ReadyzPath, nil)
|
|
handler.ServeHTTP(rec, req)
|
|
|
|
require.Equal(t, http.StatusServiceUnavailable, rec.Code)
|
|
require.Equal(t, jsonContentType, rec.Header().Get("Content-Type"))
|
|
|
|
var body errorResponse
|
|
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body))
|
|
require.Equal(t, errorCodeServiceUnavailable, body.Error.Code)
|
|
require.True(t, strings.Contains(body.Error.Message, "postgres"))
|
|
}
|
|
|
|
func TestNewServerRejectsInvalidConfig(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
_, err := NewServer(Config{}, Dependencies{})
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestRunBindsListenerAndShutsDown(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
server, err := NewServer(newTestConfig(), Dependencies{})
|
|
require.NoError(t, err)
|
|
|
|
runErr := make(chan error, 1)
|
|
go func() {
|
|
runErr <- server.Run(t.Context())
|
|
}()
|
|
|
|
require.Eventually(t, func() bool {
|
|
return server.Addr() != ""
|
|
}, time.Second, 10*time.Millisecond, "listener should bind quickly")
|
|
|
|
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), time.Second)
|
|
defer shutdownCancel()
|
|
require.NoError(t, server.Shutdown(shutdownCtx))
|
|
|
|
select {
|
|
case err := <-runErr:
|
|
require.NoError(t, err)
|
|
case <-time.After(time.Second):
|
|
t.Fatal("server did not return after shutdown")
|
|
}
|
|
}
|