func TestNextCost(t *testing.T) { pool := NewPool("test", newTestConfig()) defer pool.Shutdown() backend0 := testutils.NewBackend(0, false) defer backend0.Shutdown() backend1 := testutils.NewBackend(0, false) defer backend1.Shutdown() pool.AddServer(backend0.Address(), NewServer(backend0.Address())) pool.AddServer(backend1.Address(), NewServer(backend1.Address())) time.Sleep(50 * time.Millisecond) for _, server := range pool.Servers { if server.Address == backend0.Address() { // leaving a request open for this effect // will add to test times server.Metrics.RequestStart() } } if pool.Next().Address != backend1.Address() { t.Errorf("should return server with least cost") } }
func TestParseAndSet(t *testing.T) { status := NewServerStatus() backend := testutils.NewBackend(0, false) defer backend.Shutdown() client := &http.Client{} req, _ := http.NewRequest("GET", backend.URL()+"/healthz", nil) backend.SetStatus(http.StatusOK, "DEGRADED") res, _ := client.Do(req) status.ParseAndSet(res) if status.Current != StatusDegraded { t.Errorf("should set status to degraded from header") } backend.SetStatus(http.StatusOK, "MAINTENANCE") res, _ = client.Do(req) status.ParseAndSet(res) if status.Current != StatusMaintenance { t.Errorf("should set status to maintenance from header") } }
func TestRoundTripServerError(t *testing.T) { backend := testutils.NewBackend(0, false) backend.SetResponse(http.StatusInternalServerError, "No shit, Sherlock!") defer backend.Shutdown() server := NewServer(backend.Address()) req, _ := http.NewRequest("GET", backend.URL(), nil) resErrCh := make(chan ResponseError) go server.RoundTrip(req, resErrCh) resErr := <-resErrCh if resErr.Error != nil { // transport must not care about server's response // as long as there are no connection errors t.Errorf("should report no error") } body, _ := ioutil.ReadAll(resErr.Response.Body) if string(body) != "No shit, Sherlock!" { t.Errorf("should return server's response") } return }
func TestRunChecks(t *testing.T) { conf := newTestConfig() pool := NewPool("test", conf) defer pool.Shutdown() backend := testutils.NewBackend(0, false) defer backend.Shutdown() backend.SetStatus(http.StatusOK, "MAINTENANCE") pool.AddServer(backend.Address(), NewServer(backend.Address())) time.Sleep(50 * time.Millisecond) if pool.Servers[backend.Address()].Status.Current != StatusMaintenance { t.Errorf("should poll for server health") } conf = PoolConfig{ HealthzEvery: 2 * time.Second, HealthzTimeout: 1 * time.Second, } pool.Reconfigure(conf) time.Sleep(50 * time.Millisecond) backend.SetStatus(http.StatusOK, "OK") if pool.Servers[backend.Address()].Status.Current != StatusMaintenance { t.Errorf("should update check interval") } }
func TestCheckStatusTimeout(t *testing.T) { backend := testutils.NewBackend(100, false) defer backend.Shutdown() server := NewServer(backend.Address()) server.CheckStatus(10 * time.Millisecond) if server.Status.Current != StatusCritical { t.Errorf("should set status to critical on timeout") } }
func TestHandleResponseHeaders(t *testing.T) { backend := testutils.NewBackend(0, false) defer backend.Shutdown() server := NewServer(backend.Address()) logRecord, _ := testutils.NewTestHAProxyLogRecord(backend.URL() + "/healthz") server.Handle(logRecord, 100*time.Millisecond) if logRecord.GetResponseHeaders()["Server-Status"][0] != "OK" { t.Errorf("should copy response headers") } }
func TestNextMaintenance(t *testing.T) { pool := NewPool("test", newTestConfig()) defer pool.Shutdown() backend0 := testutils.NewBackend(0, false) defer backend0.Shutdown() backend1 := testutils.NewBackend(0, false) defer backend0.Shutdown() backend0.SetStatus(http.StatusOK, "MAINTENANCE") backend1.SetStatus(http.StatusOK, "MAINTENANCE") pool.AddServer(backend0.Address(), NewServer(backend0.Address())) pool.AddServer(backend1.Address(), NewServer(backend1.Address())) time.Sleep(50 * time.Millisecond) if pool.Next() != nil { t.Errorf("should never return server under maintenance") } }
func TestHandleXForwardedFor(t *testing.T) { backend := testutils.NewBackend(0, false) defer backend.Shutdown() server := NewServer(backend.Address()) logRecord, _ := testutils.NewTestHAProxyLogRecord(backend.URL()) server.Handle(logRecord, 100*time.Millisecond) elm := backend.Handler.Recorded.Front() rec := elm.Value.(testutils.RequestAndTime).R if rec.Header["X-Forwarded-For"] == nil { t.Errorf("should set x-forwarded-for") } }
func TestHandleResponse(t *testing.T) { backend := testutils.NewBackend(0, false) backend.SetResponse(http.StatusOK, "The eagle has landed.") defer backend.Shutdown() server := NewServer(backend.Address()) logRecord, rr := testutils.NewTestHAProxyLogRecord(backend.URL()) server.Handle(logRecord, 100*time.Millisecond) if logRecord.GetResponseStatusCode() != http.StatusOK { t.Errorf("should set status code") } body, _ := ioutil.ReadAll(rr.Body) if string(body) != "The eagle has landed." { t.Errorf("should set response body") } }
func TestHandleTimeout(t *testing.T) { backend := testutils.NewBackend(100, false) backend.SetResponse(http.StatusOK, "Ba-ba-ba-ba-ba-na-na!") defer backend.Shutdown() server := NewServer(backend.Address()) logRecord, rr := testutils.NewTestHAProxyLogRecord(backend.URL()) server.Handle(logRecord, 10*time.Millisecond) if logRecord.GetResponseStatusCode() != http.StatusGatewayTimeout || rr.Code != http.StatusGatewayTimeout { t.Errorf("should report status code 502") } body, _ := ioutil.ReadAll(rr.Body) if string(body) != "Gateway Timeout\n" { t.Errorf("should report 'Gateway Timeout'") } }
func TestRoundTripServerOk(t *testing.T) { backend := testutils.NewBackend(0, false) defer backend.Shutdown() server := NewServer(backend.Address()) req, _ := http.NewRequest("GET", backend.URL(), nil) resErrCh := make(chan ResponseError) go server.RoundTrip(req, resErrCh) resErr := <-resErrCh if resErr.Error != nil { t.Errorf("should report no error") } body, _ := ioutil.ReadAll(resErr.Response.Body) if string(body) != "testutils backend" { t.Errorf("should return server's response") } return }
func TestHandle(t *testing.T) { pool := NewPool("test", newTestConfig()) defer pool.Shutdown() backend := testutils.NewBackend(0, false) defer backend.Shutdown() backend.SetResponse(http.StatusOK, "Mickey Mouse!") pool.AddServer(backend.Address(), NewServer(backend.Address())) time.Sleep(50 * time.Millisecond) logRecord, rr := testutils.NewTestHAProxyLogRecord(backend.URL()) pool.Handle(logRecord) body, _ := ioutil.ReadAll(rr.Body) if logRecord.GetResponseStatusCode() != http.StatusOK || rr.Code != http.StatusOK || string(body) != "Mickey Mouse!" { t.Errorf("should forward requests to backend") t.Errorf("%d | %d | %s", logRecord.GetResponseStatusCode, rr.Code, string(body)) } }
func TestCheckStatus(t *testing.T) { backend := testutils.NewBackend(0, false) defer backend.Shutdown() server := NewServer(backend.Address()) backend.SetStatus(http.StatusInternalServerError, "UNKNOWN") server.CheckStatus(100 * time.Millisecond) if server.Status.Current != StatusUnknown { t.Errorf("should set status to unknown") } backend.SetStatus(http.StatusOK, "MainTENANCE") server.CheckStatus(100 * time.Millisecond) if server.Status.Current != StatusMaintenance { t.Errorf("should set status to maintenance") } backend.SetStatus(http.StatusOK, "DEGRADED") server.CheckStatus(100 * time.Millisecond) if server.Status.Current != StatusDegraded { t.Errorf("should parse response headers on 200s") } }