README update for sonarcloud badges, simplify some test code, fixed some sonarlint issues

This commit is contained in:
yusing 2024-09-17 04:51:26 +08:00
parent 409a18df38
commit 04fd6543fd
6 changed files with 106 additions and 87 deletions

View file

@ -2,13 +2,12 @@ FROM golang:1.23.1-alpine AS builder
COPY src /src COPY src /src
ENV GOCACHE=/root/.cache/go-build ENV GOCACHE=/root/.cache/go-build
WORKDIR /src WORKDIR /src
RUN --mount=type=cache,target="/go/pkg/mod" \
go mod download
RUN --mount=type=cache,target="/go/pkg/mod" \ RUN --mount=type=cache,target="/go/pkg/mod" \
--mount=type=cache,target="/root/.cache/go-build" \ --mount=type=cache,target="/root/.cache/go-build" \
go mod download
CGO_ENABLED=0 GOOS=linux go build -pgo=auto -o go-proxy github.com/yusing/go-proxy CGO_ENABLED=0 GOOS=linux go build -pgo=auto -o go-proxy github.com/yusing/go-proxy
FROM alpine:latest FROM alpine:3.20
LABEL maintainer="yusing@6uo.me" LABEL maintainer="yusing@6uo.me"

View file

@ -1,5 +1,11 @@
# go-proxy # go-proxy
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=yusing_go-proxy&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=yusing_go-proxy)
[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=yusing_go-proxy&metric=ncloc)](https://sonarcloud.io/summary/new_code?id=yusing_go-proxy)
[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=yusing_go-proxy&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=yusing_go-proxy)
[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=yusing_go-proxy&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=yusing_go-proxy)
[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=yusing_go-proxy&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=yusing_go-proxy)
A [lightweight](docs/benchmark_result.md), easy-to-use, and efficient reverse proxy and load balancer with a web UI. A [lightweight](docs/benchmark_result.md), easy-to-use, and efficient reverse proxy and load balancer with a web UI.
**Table of content** **Table of content**

View file

@ -29,10 +29,10 @@ func List(cfg *config.Config, w http.ResponseWriter, r *http.Request) {
func listRoutes(cfg *config.Config, w http.ResponseWriter, r *http.Request) { func listRoutes(cfg *config.Config, w http.ResponseWriter, r *http.Request) {
routes := cfg.RoutesByAlias() routes := cfg.RoutesByAlias()
type_filter := r.FormValue("type") typeFilter := r.FormValue("type")
if type_filter != "" { if typeFilter != "" {
for k, v := range routes { for k, v := range routes {
if v["type"] != type_filter { if v["type"] != typeFilter {
delete(routes, k) delete(routes, k)
} }
} }

View file

@ -7,6 +7,7 @@ import (
"testing" "testing"
E "github.com/yusing/go-proxy/error" E "github.com/yusing/go-proxy/error"
. "github.com/yusing/go-proxy/utils"
) )
func makeLabel(namespace string, alias string, field string) string { func makeLabel(namespace string, alias string, field string) string {
@ -18,29 +19,23 @@ func TestHomePageLabel(t *testing.T) {
field := "ip" field := "ip"
v := "bar" v := "bar"
pl, err := ParseLabel(makeLabel(NSHomePage, alias, field), v) pl, err := ParseLabel(makeLabel(NSHomePage, alias, field), v)
if err.IsNotNil() { ExpectErrNil(t, err)
t.Errorf("expected err=nil, got %s", err.Error())
}
if pl.Target != alias { if pl.Target != alias {
t.Errorf("expected alias=%s, got %s", alias, pl.Target) t.Errorf("Expected alias=%s, got %s", alias, pl.Target)
} }
if pl.Attribute != field { if pl.Attribute != field {
t.Errorf("expected field=%s, got %s", field, pl.Target) t.Errorf("Expected field=%s, got %s", field, pl.Target)
} }
if pl.Value != v { if pl.Value != v {
t.Errorf("expected value=%q, got %s", v, pl.Value) t.Errorf("Expected value=%q, got %s", v, pl.Value)
} }
} }
func TestStringProxyLabel(t *testing.T) { func TestStringProxyLabel(t *testing.T) {
v := "bar" v := "bar"
pl, err := ParseLabel(makeLabel(NSProxy, "foo", "ip"), v) pl, err := ParseLabel(makeLabel(NSProxy, "foo", "ip"), v)
if err.IsNotNil() { ExpectErrNil(t, err)
t.Errorf("expected err=nil, got %s", err.Error()) ExpectEqual(t, pl.Value, v)
}
if pl.Value != v {
t.Errorf("expected value=%q, got %s", v, pl.Value)
}
} }
func TestBoolProxyLabelValid(t *testing.T) { func TestBoolProxyLabelValid(t *testing.T) {
@ -57,12 +52,8 @@ func TestBoolProxyLabelValid(t *testing.T) {
for k, v := range tests { for k, v := range tests {
pl, err := ParseLabel(makeLabel(NSProxy, "foo", "no_tls_verify"), k) pl, err := ParseLabel(makeLabel(NSProxy, "foo", "no_tls_verify"), k)
if err.IsNotNil() { ExpectErrNil(t, err)
t.Errorf("expected err=nil, got %s", err.Error()) ExpectEqual(t, pl.Value, v)
}
if pl.Value != v {
t.Errorf("expected value=%v, got %v", v, pl.Value)
}
} }
} }
@ -71,7 +62,7 @@ func TestBoolProxyLabelInvalid(t *testing.T) {
field := "no_tls_verify" field := "no_tls_verify"
_, err := ParseLabel(makeLabel(NSProxy, alias, field), "invalid") _, err := ParseLabel(makeLabel(NSProxy, alias, field), "invalid")
if !err.Is(E.ErrInvalid) { if !err.Is(E.ErrInvalid) {
t.Errorf("expected err InvalidProxyLabel, got %s", err.Error()) t.Errorf("Expected err InvalidProxyLabel, got %s", err.Error())
} }
} }
@ -87,17 +78,12 @@ X-Custom-Header2: boo`
} }
pl, err := ParseLabel(makeLabel(NSProxy, "foo", "set_headers"), v) pl, err := ParseLabel(makeLabel(NSProxy, "foo", "set_headers"), v)
if err.IsNotNil() { ExpectErrNil(t, err)
t.Errorf("expected err=nil, got %s", err.Error()) hGot := ExpectType[map[string]string](t, pl.Value)
} if hGot != nil && !reflect.DeepEqual(h, hGot) {
hGot, ok := pl.Value.(map[string]string) t.Errorf("Expected %v, got %v", h, hGot)
if !ok {
t.Errorf("value is not a map[string]string, but %T", pl.Value)
return
}
if !reflect.DeepEqual(h, hGot) {
t.Errorf("expected %v, got %v", h, hGot)
} }
} }
func TestSetHeaderProxyLabelInvalid(t *testing.T) { func TestSetHeaderProxyLabelInvalid(t *testing.T) {
@ -110,7 +96,7 @@ func TestSetHeaderProxyLabelInvalid(t *testing.T) {
for _, v := range tests { for _, v := range tests {
_, err := ParseLabel(makeLabel(NSProxy, "foo", "set_headers"), v) _, err := ParseLabel(makeLabel(NSProxy, "foo", "set_headers"), v)
if !err.Is(E.ErrInvalid) { if !err.Is(E.ErrInvalid) {
t.Errorf("expected invalid err for %q, got %s", v, err.Error()) t.Errorf("Expected invalid err for %q, got %s", v, err.Error())
} }
} }
} }
@ -123,47 +109,33 @@ func TestHideHeadersProxyLabel(t *testing.T) {
` `
v = strings.TrimPrefix(v, "\n") v = strings.TrimPrefix(v, "\n")
pl, err := ParseLabel(makeLabel(NSProxy, "foo", "hide_headers"), v) pl, err := ParseLabel(makeLabel(NSProxy, "foo", "hide_headers"), v)
if err.IsNotNil() { ExpectErrNil(t, err)
t.Errorf("expected err=nil, got %s", err.Error()) sGot := ExpectType[[]string](t, pl.Value)
}
sGot, ok := pl.Value.([]string)
sWant := []string{"X-Custom-Header1", "X-Custom-Header2", "X-Custom-Header3"} sWant := []string{"X-Custom-Header1", "X-Custom-Header2", "X-Custom-Header3"}
if !ok { if sGot != nil {
t.Errorf("value is not []string, but %T", pl.Value) ExpectEqual(t, sGot, sWant)
}
if !reflect.DeepEqual(sGot, sWant) {
t.Errorf("expected %q, got %q", sWant, sGot)
} }
} }
func TestCommaSepProxyLabelSingle(t *testing.T) { func TestCommaSepProxyLabelSingle(t *testing.T) {
v := "a" v := "a"
pl, err := ParseLabel("proxy.aliases", v) pl, err := ParseLabel("proxy.aliases", v)
if err.IsNotNil() { ExpectErrNil(t, err)
t.Errorf("expected err=nil, got %s", err.Error()) sGot := ExpectType[[]string](t, pl.Value)
}
sGot, ok := pl.Value.([]string)
sWant := []string{"a"} sWant := []string{"a"}
if !ok { if sGot != nil {
t.Errorf("value is not []string, but %T", pl.Value) ExpectEqual(t, sGot, sWant)
}
if !reflect.DeepEqual(sGot, sWant) {
t.Errorf("expected %q, got %q", sWant, sGot)
} }
} }
func TestCommaSepProxyLabelMulti(t *testing.T) { func TestCommaSepProxyLabelMulti(t *testing.T) {
v := "X-Custom-Header1, X-Custom-Header2,X-Custom-Header3" v := "X-Custom-Header1, X-Custom-Header2,X-Custom-Header3"
pl, err := ParseLabel("proxy.aliases", v) pl, err := ParseLabel("proxy.aliases", v)
if err.IsNotNil() { ExpectErrNil(t, err)
t.Errorf("expected err=nil, got %s", err.Error()) sGot := ExpectType[[]string](t, pl.Value)
}
sGot, ok := pl.Value.([]string)
sWant := []string{"X-Custom-Header1", "X-Custom-Header2", "X-Custom-Header3"} sWant := []string{"X-Custom-Header1", "X-Custom-Header2", "X-Custom-Header3"}
if !ok { if sGot != nil {
t.Errorf("value is not []string, but %T", pl.Value) ExpectEqual(t, sGot, sWant)
}
if !reflect.DeepEqual(sGot, sWant) {
t.Errorf("expected %q, got %q", sWant, sGot)
} }
} }

View file

@ -1,46 +1,42 @@
package error package error_test
import ( import (
"testing" "testing"
. "github.com/yusing/go-proxy/error"
. "github.com/yusing/go-proxy/utils"
) )
func AssertEq[T comparable](t *testing.T, got, want T) {
t.Helper()
if got != want {
t.Errorf("expected:\n%v, got\n%v", want, got)
}
}
func TestErrorIs(t *testing.T) { func TestErrorIs(t *testing.T) {
AssertEq(t, Failure("foo").Is(ErrFailure), true) ExpectTrue(t, Failure("foo").Is(ErrFailure))
AssertEq(t, Failure("foo").With("bar").Is(ErrFailure), true) ExpectTrue(t, Failure("foo").With("bar").Is(ErrFailure))
AssertEq(t, Failure("foo").With("bar").Is(ErrInvalid), false) ExpectFalse(t, Failure("foo").With("bar").Is(ErrInvalid))
AssertEq(t, Failure("foo").With("bar").With("baz").Is(ErrInvalid), false) ExpectFalse(t, Failure("foo").With("bar").With("baz").Is(ErrInvalid))
AssertEq(t, Invalid("foo", "bar").Is(ErrInvalid), true) ExpectTrue(t, Invalid("foo", "bar").Is(ErrInvalid))
AssertEq(t, Invalid("foo", "bar").Is(ErrFailure), false) ExpectFalse(t, Invalid("foo", "bar").Is(ErrFailure))
AssertEq(t, Nil().Is(nil), true) ExpectTrue(t, Nil().Is(nil))
AssertEq(t, Nil().Is(ErrInvalid), false) ExpectFalse(t, Nil().Is(ErrInvalid))
AssertEq(t, Invalid("foo", "bar").Is(nil), false) ExpectFalse(t, Invalid("foo", "bar").Is(nil))
} }
func TestNil(t *testing.T) { func TestNil(t *testing.T) {
AssertEq(t, Nil().IsNil(), true) ExpectTrue(t, Nil().IsNil())
AssertEq(t, Nil().IsNotNil(), false) ExpectFalse(t, Nil().IsNotNil())
AssertEq(t, Nil().Error(), "nil") ExpectEqual(t, Nil().Error(), "nil")
} }
func TestErrorSimple(t *testing.T) { func TestErrorSimple(t *testing.T) {
ne := Failure("foo bar") ne := Failure("foo bar")
AssertEq(t, ne.Error(), "foo bar failed") ExpectEqual(t, ne.Error(), "foo bar failed")
ne = ne.Subject("baz") ne = ne.Subject("baz")
AssertEq(t, ne.Error(), "foo bar failed for \"baz\"") ExpectEqual(t, ne.Error(), "foo bar failed for \"baz\"")
} }
func TestErrorWith(t *testing.T) { func TestErrorWith(t *testing.T) {
ne := Failure("foo").With("bar").With("baz") ne := Failure("foo").With("bar").With("baz")
AssertEq(t, ne.Error(), "foo failed:\n - bar\n - baz") ExpectEqual(t, ne.Error(), "foo failed:\n - bar\n - baz")
} }
func TestErrorNested(t *testing.T) { func TestErrorNested(t *testing.T) {
@ -76,5 +72,5 @@ func TestErrorNested(t *testing.T) {
- inner3 failed for "action 3": - inner3 failed for "action 3":
- 3 - 3
- 3` - 3`
AssertEq(t, ne.Error(), want) ExpectEqual(t, ne.Error(), want)
} }

46
src/utils/testing.go Normal file
View file

@ -0,0 +1,46 @@
package utils
import (
"reflect"
"testing"
E "github.com/yusing/go-proxy/error"
)
func ExpectErrNil(t *testing.T, err E.NestedError) {
t.Helper()
if err.IsNotNil() {
t.Errorf("expected err=nil, got %s", err.Error())
}
}
func ExpectEqual(t *testing.T, got, want any) {
t.Helper()
if !reflect.DeepEqual(got, want) {
t.Errorf("expected:\n%v, got\n%v", want, got)
}
}
func ExpectTrue(t *testing.T, got bool) {
t.Helper()
if !got {
t.Errorf("expected true, got false")
}
}
func ExpectFalse(t *testing.T, got bool) {
t.Helper()
if got {
t.Errorf("expected false, got true")
}
}
func ExpectType[T any](t *testing.T, got any) T {
t.Helper()
tExpect := reflect.TypeFor[T]()
_, ok := got.(T)
if !ok {
t.Errorf("expected type %T, got %T", tExpect, got)
}
return got.(T)
}