refactor(handler/http2): split handler into 3 focused files with 52 tests
Extract authenticate/probe-resistance to auth.go and roundTrip/forwarding to proxy.go, following the handler/http/ pattern. Export sentinel errors (ErrAuthFailed, ErrWrongConnType) for precise test assertions. Fix flushWriter panic recovery to handle non-string/non-error panics. Default HTTPS port to 443 when no port is specified in the Host header.
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
package http2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-gost/core/handler"
|
||||
)
|
||||
|
||||
func TestNewHandler(t *testing.T) {
|
||||
h := NewHandler()
|
||||
if h == nil {
|
||||
t.Fatal("NewHandler returned nil")
|
||||
}
|
||||
h2, ok := h.(*http2Handler)
|
||||
if !ok {
|
||||
t.Fatalf("NewHandler returned %T, want *http2Handler", h)
|
||||
}
|
||||
if h2.options.Logger != nil {
|
||||
t.Error("expected nil logger by default")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClose(t *testing.T) {
|
||||
h := newTestHandler()
|
||||
if err := h.Close(); err != nil {
|
||||
t.Fatalf("Close: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCloseAfterInit(t *testing.T) {
|
||||
h := newTestHandler()
|
||||
if err := h.Init(testMD(map[string]any{})); err != nil {
|
||||
t.Fatalf("Init: %v", err)
|
||||
}
|
||||
if h.cancel == nil {
|
||||
t.Fatal("cancel not set after Init")
|
||||
}
|
||||
if err := h.Close(); err != nil {
|
||||
t.Fatalf("Close after Init: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInit(t *testing.T) {
|
||||
h := newTestHandler(handler.ObserverOption(&testObserver{}))
|
||||
if err := h.Init(testMD(map[string]any{})); err != nil {
|
||||
t.Fatalf("Init: %v", err)
|
||||
}
|
||||
if h.stats == nil {
|
||||
t.Error("stats not set when observer configured")
|
||||
}
|
||||
if h.cancel == nil {
|
||||
t.Error("cancel not set")
|
||||
}
|
||||
h.Close()
|
||||
}
|
||||
|
||||
func TestInit_Limiter(t *testing.T) {
|
||||
h := newTestHandler(handler.TrafficLimiterOption(&stubTrafficLimiter{}))
|
||||
if err := h.Init(testMD(map[string]any{})); err != nil {
|
||||
t.Fatalf("Init: %v", err)
|
||||
}
|
||||
if h.limiter == nil {
|
||||
t.Error("limiter not set")
|
||||
}
|
||||
h.Close()
|
||||
}
|
||||
|
||||
func TestObserveStats_NilObserver(t *testing.T) {
|
||||
h := newTestHandler()
|
||||
// Should return immediately without panicking.
|
||||
h.observeStats(context.Background())
|
||||
}
|
||||
|
||||
func TestObserveStats_CancelledContext(t *testing.T) {
|
||||
h := newTestHandler()
|
||||
h.md.observerPeriod = 5 * time.Second
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
h.observeStats(ctx)
|
||||
}
|
||||
|
||||
func TestCheckRateLimit(t *testing.T) {
|
||||
t.Run("no limiter", func(t *testing.T) {
|
||||
h := newTestHandler()
|
||||
addr := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 12345}
|
||||
if !h.checkRateLimit(addr) {
|
||||
t.Error("expected true without limiter")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("with limiter", func(t *testing.T) {
|
||||
h := newTestHandler(handler.RateLimiterOption(newStubRateLimiter()))
|
||||
addr := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 12345}
|
||||
if !h.checkRateLimit(addr) {
|
||||
t.Error("expected true with always-allow limiter")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestHandle_WrongConnType(t *testing.T) {
|
||||
h := newTestHandler()
|
||||
if err := h.Init(testMD(map[string]any{})); err != nil {
|
||||
t.Fatalf("Init: %v", err)
|
||||
}
|
||||
client, server := net.Pipe()
|
||||
defer client.Close()
|
||||
defer server.Close()
|
||||
|
||||
err := h.Handle(context.Background(), server)
|
||||
if err != ErrWrongConnType {
|
||||
t.Errorf("err = %v, want ErrWrongConnType", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user