unittest, typos

This commit is contained in:
nikolay.bystritskiy
2021-05-07 22:27:37 +02:00
committed by Umputun
parent 973d6c9a14
commit 7bbb7073ba
4 changed files with 143 additions and 1 deletions

View File

@@ -151,7 +151,7 @@ func (s *Service) Match(srv, src string) (string, MatchType, bool) {
// ScheduleHealthCheck starts background loop with health-check
func (s *Service) ScheduleHealthCheck(ctx context.Context, interval time.Duration) {
log.Printf("health-check scheduled every %s seconds", interval)
log.Printf("health-check scheduled every %s", interval)
go func() {
hloop:
@@ -163,6 +163,7 @@ func (s *Service) ScheduleHealthCheck(ctx context.Context, interval time.Duratio
cres := CheckHealth(s.Mappers())
s.lock.RUnlock()
// alive services would be picked up first
sort.SliceStable(cres.mappers, func(i, j int) bool {
return cres.mappers[j].dead
})

View File

@@ -3,6 +3,10 @@ package discovery
import (
"context"
"errors"
"fmt"
"math/rand"
"net/http"
"net/http/httptest"
"regexp"
"strconv"
"testing"
@@ -223,3 +227,53 @@ func TestService_extendRule(t *testing.T) {
}
}
func TestService_ScheduleHealthCheck(t *testing.T) {
randomPort := rand.Intn(10000) + 40000
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK"))
}))
defer ts.Close()
ts2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK"))
}))
defer ts2.Close()
wantMappers := []URLMapper{
{SrcMatch: *regexp.MustCompile("/api/svc3/xyz"), Dst: "http://127.0.0.3:8080/blah3/xyz", ProviderID: PIDocker, PingURL: ts.URL},
{SrcMatch: *regexp.MustCompile("/api/svc3/xyz"), Dst: "http://127.0.0.3:8080/blah3/xyz", ProviderID: PIDocker, PingURL: fmt.Sprintf("127.0.0.1:%d", randomPort)},
{SrcMatch: *regexp.MustCompile("/api/svc3/xyz"), Dst: "http://127.0.0.3:8080/blah3/xyz", ProviderID: PIDocker, PingURL: ts2.URL},
}
p := &ProviderMock{
EventsFunc: func(ctx context.Context) <-chan ProviderID {
res := make(chan ProviderID, 1)
res <- PIFile
return res
},
ListFunc: func() ([]URLMapper, error) {
return wantMappers, nil
},
}
svc := NewService([]Provider{p}, time.Millisecond*10)
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()
err := svc.Run(ctx)
require.Error(t, err)
assert.Equal(t, context.DeadlineExceeded, err)
mappers := svc.Mappers()
assert.Equal(t, 3, len(mappers))
assert.Equal(t, wantMappers, mappers)
svc.ScheduleHealthCheck(context.Background(), time.Microsecond*2)
time.Sleep(time.Millisecond * 10)
mappers = svc.Mappers()
assert.Equal(t, false, mappers[0].dead)
assert.Equal(t, false, mappers[1].dead)
assert.Equal(t, true, mappers[2].dead)
}

View File

@@ -9,6 +9,7 @@ import (
"time"
)
// CheckResult is result of health-check
type CheckResult struct {
Ok bool
Valid int
@@ -17,6 +18,7 @@ type CheckResult struct {
mappers []URLMapper
}
// CheckHealth starts health-check for service's mappers
func CheckHealth(mappers []URLMapper) CheckResult {
const concurrent = 8
sema := make(chan struct{}, concurrent) // limit health check to 8 concurrent calls

View File

@@ -1 +1,86 @@
package discovery
import (
"fmt"
"math/rand"
"net/http"
"net/http/httptest"
"testing"
)
func Test_ping(t *testing.T) {
port := rand.Intn(10000) + 40000
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK"))
}))
defer ts.Close()
ts2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(500)
}))
defer ts2.Close()
type args struct {
m URLMapper
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
{name: "test server, expected OK", args: args{m: URLMapper{PingURL: ts.URL}}, want: "", wantErr: false},
{name: "random port, expected error", args: args{m: URLMapper{PingURL: fmt.Sprintf("127.0.0.1:%d", port)}}, want: "", wantErr: true},
{name: "error code != 200", args: args{m: URLMapper{PingURL: ts2.URL}}, want: "", wantErr: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := ping(tt.args.m)
if (err != nil) != tt.wantErr {
t.Errorf("ping() error = %v, wantErr %v", err, tt.wantErr)
return
}
})
}
}
func TestCheckHealth(t *testing.T) {
port := rand.Intn(10000) + 40000
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK"))
}))
defer ts.Close()
ts2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK"))
}))
defer ts2.Close()
type args struct {
mappers []URLMapper
}
tests := []struct {
name string
args args
want CheckResult
}{
{name: "case 1", args: args{mappers: []URLMapper{{PingURL: ts.URL}, {PingURL: ts2.URL}, {PingURL: fmt.Sprintf("127.0.0.1:%d", port)}}},
want: CheckResult{Ok: false, Total: 3, Valid: 2, mappers: []URLMapper{{PingURL: ts.URL, dead: false}, {PingURL: ts2.URL, dead: false},
{PingURL: fmt.Sprintf("127.0.0.1:%d", port), dead: true}}}},
{name: "case 2", args: args{mappers: []URLMapper{{PingURL: ts.URL}, {PingURL: ts2.URL}}},
want: CheckResult{Ok: true, Total: 2, Valid: 2, mappers: []URLMapper{{PingURL: ts.URL, dead: false}, {PingURL: ts2.URL, dead: false}}}},
{name: "case 3", args: args{mappers: []URLMapper{{PingURL: ts.URL, MatchType: MTStatic}, {PingURL: ts2.URL}}},
want: CheckResult{Ok: true, Total: 1, Valid: 1, mappers: []URLMapper{{PingURL: ts.URL, dead: false}, {PingURL: ts2.URL, dead: false}}}},
{name: "case 4", args: args{mappers: []URLMapper{{}, {PingURL: ts2.URL}}},
want: CheckResult{Ok: true, Total: 2, Valid: 1, mappers: []URLMapper{{PingURL: ts.URL, dead: false}, {PingURL: ts2.URL, dead: true}}}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := CheckHealth(tt.args.mappers)
got.Errs = got.Errs[:0]
if got.Ok != tt.want.Ok || got.Total != tt.want.Total || got.Valid != tt.want.Valid {
t.Errorf("CheckHealth() = %v, want %v", got, tt.want)
}
})
}
}