test: HealthCheck review.
This commit is contained in:
parent
a1a0420314
commit
2d1ddcf28b
2 changed files with 82 additions and 81 deletions
|
@ -2,7 +2,6 @@ package healthcheck
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -10,87 +9,17 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/containous/traefik/testhelpers"
|
||||||
"github.com/vulcand/oxy/roundrobin"
|
"github.com/vulcand/oxy/roundrobin"
|
||||||
)
|
)
|
||||||
|
|
||||||
const healthCheckInterval = 100 * time.Millisecond
|
const healthCheckInterval = 100 * time.Millisecond
|
||||||
|
|
||||||
type testLoadBalancer struct {
|
|
||||||
// RWMutex needed due to parallel test execution: Both the system-under-test
|
|
||||||
// and the test assertions reference the counters.
|
|
||||||
*sync.RWMutex
|
|
||||||
numRemovedServers int
|
|
||||||
numUpsertedServers int
|
|
||||||
servers []*url.URL
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lb *testLoadBalancer) RemoveServer(u *url.URL) error {
|
|
||||||
lb.Lock()
|
|
||||||
defer lb.Unlock()
|
|
||||||
lb.numRemovedServers++
|
|
||||||
lb.removeServer(u)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lb *testLoadBalancer) UpsertServer(u *url.URL, options ...roundrobin.ServerOption) error {
|
|
||||||
lb.Lock()
|
|
||||||
defer lb.Unlock()
|
|
||||||
lb.numUpsertedServers++
|
|
||||||
lb.servers = append(lb.servers, u)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lb *testLoadBalancer) Servers() []*url.URL {
|
|
||||||
return lb.servers
|
|
||||||
}
|
|
||||||
|
|
||||||
func (lb *testLoadBalancer) removeServer(u *url.URL) {
|
|
||||||
var i int
|
|
||||||
var serverURL *url.URL
|
|
||||||
for i, serverURL = range lb.servers {
|
|
||||||
if *serverURL == *u {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lb.servers = append(lb.servers[:i], lb.servers[i+1:]...)
|
|
||||||
}
|
|
||||||
|
|
||||||
type testHandler struct {
|
type testHandler struct {
|
||||||
done func()
|
done func()
|
||||||
healthSequence []bool
|
healthSequence []bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestServer(done func(), healthSequence []bool) *httptest.Server {
|
|
||||||
handler := &testHandler{
|
|
||||||
done: done,
|
|
||||||
healthSequence: healthSequence,
|
|
||||||
}
|
|
||||||
return httptest.NewServer(handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServeHTTP returns 200 or 503 HTTP response codes depending on whether the
|
|
||||||
// current request is marked as healthy or not.
|
|
||||||
// It calls the given 'done' function once all request health indicators have
|
|
||||||
// been depleted.
|
|
||||||
func (th *testHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if len(th.healthSequence) == 0 {
|
|
||||||
panic("received unexpected request")
|
|
||||||
}
|
|
||||||
|
|
||||||
healthy := th.healthSequence[0]
|
|
||||||
if healthy {
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
} else {
|
|
||||||
w.WriteHeader(http.StatusServiceUnavailable)
|
|
||||||
}
|
|
||||||
|
|
||||||
th.healthSequence = th.healthSequence[1:]
|
|
||||||
if len(th.healthSequence) == 0 {
|
|
||||||
th.done()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSetBackendsConfiguration(t *testing.T) {
|
func TestSetBackendsConfiguration(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
desc string
|
desc string
|
||||||
|
@ -153,20 +82,20 @@ func TestSetBackendsConfiguration(t *testing.T) {
|
||||||
Interval: healthCheckInterval,
|
Interval: healthCheckInterval,
|
||||||
LB: lb,
|
LB: lb,
|
||||||
})
|
})
|
||||||
serverURL := MustParseURL(ts.URL)
|
serverURL := testhelpers.MustParseURL(ts.URL)
|
||||||
if test.startHealthy {
|
if test.startHealthy {
|
||||||
lb.servers = append(lb.servers, serverURL)
|
lb.servers = append(lb.servers, serverURL)
|
||||||
} else {
|
} else {
|
||||||
backend.disabledURLs = append(backend.disabledURLs, serverURL)
|
backend.disabledURLs = append(backend.disabledURLs, serverURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
healthCheck := HealthCheck{
|
check := HealthCheck{
|
||||||
Backends: make(map[string]*BackendHealthCheck),
|
Backends: make(map[string]*BackendHealthCheck),
|
||||||
}
|
}
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
healthCheck.execute(ctx, "id", backend)
|
check.execute(ctx, "id", backend)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -257,13 +186,75 @@ func TestNewRequest(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func MustParseURL(rawurl string) *url.URL {
|
type testLoadBalancer struct {
|
||||||
u, err := url.Parse(rawurl)
|
// RWMutex needed due to parallel test execution: Both the system-under-test
|
||||||
if err != nil {
|
// and the test assertions reference the counters.
|
||||||
panic(fmt.Sprintf("failed to parse URL '%s': %s", rawurl, err))
|
*sync.RWMutex
|
||||||
|
numRemovedServers int
|
||||||
|
numUpsertedServers int
|
||||||
|
servers []*url.URL
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lb *testLoadBalancer) RemoveServer(u *url.URL) error {
|
||||||
|
lb.Lock()
|
||||||
|
defer lb.Unlock()
|
||||||
|
lb.numRemovedServers++
|
||||||
|
lb.removeServer(u)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lb *testLoadBalancer) UpsertServer(u *url.URL, options ...roundrobin.ServerOption) error {
|
||||||
|
lb.Lock()
|
||||||
|
defer lb.Unlock()
|
||||||
|
lb.numUpsertedServers++
|
||||||
|
lb.servers = append(lb.servers, u)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lb *testLoadBalancer) Servers() []*url.URL {
|
||||||
|
return lb.servers
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lb *testLoadBalancer) removeServer(u *url.URL) {
|
||||||
|
var i int
|
||||||
|
var serverURL *url.URL
|
||||||
|
for i, serverURL = range lb.servers {
|
||||||
|
if *serverURL == *u {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lb.servers = append(lb.servers[:i], lb.servers[i+1:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTestServer(done func(), healthSequence []bool) *httptest.Server {
|
||||||
|
handler := &testHandler{
|
||||||
|
done: done,
|
||||||
|
healthSequence: healthSequence,
|
||||||
|
}
|
||||||
|
return httptest.NewServer(handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServeHTTP returns 200 or 503 HTTP response codes depending on whether the
|
||||||
|
// current request is marked as healthy or not.
|
||||||
|
// It calls the given 'done' function once all request health indicators have
|
||||||
|
// been depleted.
|
||||||
|
func (th *testHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if len(th.healthSequence) == 0 {
|
||||||
|
panic("received unexpected request")
|
||||||
|
}
|
||||||
|
|
||||||
|
healthy := th.healthSequence[0]
|
||||||
|
if healthy {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
} else {
|
||||||
|
w.WriteHeader(http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
|
||||||
|
th.healthSequence = th.healthSequence[1:]
|
||||||
|
if len(th.healthSequence) == 0 {
|
||||||
|
th.done()
|
||||||
}
|
}
|
||||||
return u
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Intp returns a pointer to the given integer value.
|
// Intp returns a pointer to the given integer value.
|
||||||
|
@ -19,3 +20,12 @@ func MustNewRequest(method, urlStr string, body io.Reader) *http.Request {
|
||||||
}
|
}
|
||||||
return request
|
return request
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MustParseURL parses a URL or panics if it can't
|
||||||
|
func MustParseURL(rawURL string) *url.URL {
|
||||||
|
u, err := url.Parse(rawURL)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to parse URL '%s': %s", rawURL, err))
|
||||||
|
}
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue