- Registry neither-interface, nil-registry, and authenticate default - MemoryStore sweep actually drops expired entries - RegisterHouseMiddlewareFactory duplicate-name failure - pathScopedCORS unmatched path plus empty-raw-group introspection - Time UnmarshalJSON +00:00/Z and PublicOnlyMode host/IP cases
91 lines
2.4 KiB
Go
91 lines
2.4 KiB
Go
package surf
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/netip"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.golem15.com/golem15/summercms/compass"
|
|
)
|
|
|
|
// Gap (b): MemoryStore's sweep goroutine (purge), not TooManyAttempts' lazy
|
|
// expiry. Construct with a short sweep and assert the internal map drops
|
|
// an expired entry without calling TooManyAttempts.
|
|
|
|
func TestMemoryStoreSweepRemovesExpiredEntry(t *testing.T) {
|
|
s := NewMemoryStore(15 * time.Millisecond)
|
|
t.Cleanup(func() { close(s.stop) })
|
|
|
|
s.Hit("k", 25*time.Millisecond)
|
|
s.mu.Lock()
|
|
n := len(s.entries)
|
|
s.mu.Unlock()
|
|
if n != 1 {
|
|
t.Fatalf("after Hit, entries = %d", n)
|
|
}
|
|
|
|
deadline := time.Now().Add(200 * time.Millisecond)
|
|
for time.Now().Before(deadline) {
|
|
s.mu.Lock()
|
|
n = len(s.entries)
|
|
s.mu.Unlock()
|
|
if n == 0 {
|
|
return
|
|
}
|
|
time.Sleep(10 * time.Millisecond)
|
|
}
|
|
t.Fatalf("sweep did not drop expired entry, count=%d", n)
|
|
}
|
|
|
|
func TestMemoryStoreAvailableInExpiredAndMissing(t *testing.T) {
|
|
s := NewMemoryStore(0)
|
|
if d := s.AvailableIn("missing"); d != 0 {
|
|
t.Fatalf("missing AvailableIn = %s", d)
|
|
}
|
|
s.Hit("k", 20*time.Millisecond)
|
|
if d := s.AvailableIn("k"); d <= 0 {
|
|
t.Fatalf("live AvailableIn = %s", d)
|
|
}
|
|
time.Sleep(30 * time.Millisecond)
|
|
if d := s.AvailableIn("k"); d != 0 {
|
|
t.Fatalf("expired AvailableIn = %s", d)
|
|
}
|
|
}
|
|
|
|
func TestTrustedProxiesParsesConfig(t *testing.T) {
|
|
if TrustedProxies(nil) != nil {
|
|
t.Fatal("nil cfg must return nil")
|
|
}
|
|
dir := t.TempDir()
|
|
if err := os.WriteFile(filepath.Join(dir, "app.yaml"), []byte("name: t\n"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(dir, "http.yaml"), []byte("trusted_proxies:\n - 10.0.0.0/8\n - not-a-cidr\n - 192.168.0.0/16\n"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
cfg, err := compass.Open(compass.Options{Dir: dir, Environ: []string{}})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
got := TrustedProxies(cfg)
|
|
if len(got) != 2 || got[0].String() != "10.0.0.0/8" || got[1].String() != "192.168.0.0/16" {
|
|
t.Fatalf("TrustedProxies = %v", got)
|
|
}
|
|
}
|
|
|
|
func TestClientIPNilRequestAndEmptyXFF(t *testing.T) {
|
|
if got := ClientIP(nil, nil); got != "" {
|
|
t.Fatalf("nil request = %q", got)
|
|
}
|
|
trusted := []netip.Prefix{mustPrefix("10.0.0.0/8")}
|
|
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
req.RemoteAddr = "10.0.0.1:443"
|
|
if got := ClientIP(req, trusted); got != "10.0.0.1" {
|
|
t.Fatalf("trusted RemoteAddr, empty XFF = %q", got)
|
|
}
|
|
}
|