package middleware import ( "net/http/httptest" "testing" "time" "github.com/gin-gonic/gin" "github.com/sundynix/sundynix-gateway/internal/auth" ) // A5:进程内兜底限流——固定窗口内超限即拒,过窗后恢复。Redis 挂时靠它 fail-safe。 func TestProcLimiter(t *testing.T) { l := newProcLimiter(time.Minute) now := time.Now() for i := 0; i < 3; i++ { if !l.allow("k", 3, now) { t.Fatalf("前 3 次应放行(第 %d 次被拒)", i+1) } } if l.allow("k", 3, now) { t.Fatal("超限第 4 次应拒") } if !l.allow("k", 3, now.Add(2*time.Minute)) { t.Fatal("新窗口应恢复放行") } } // A6:AuthFromHeaderOrQuery——?token= 有效则注入 uid、无 token 则 401。 func TestAuthFromHeaderOrQuery(t *testing.T) { gin.SetMode(gin.TestMode) tok, err := auth.Issue("u1") if err != nil { t.Fatalf("签发失败: %v", err) } w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Request = httptest.NewRequest("GET", "/x?token="+tok, nil) AuthFromHeaderOrQuery()(c) if c.IsAborted() { t.Fatal("有效 query token 不该被拦") } if v, _ := c.Get(CtxUserID); v != "u1" { t.Fatalf("应注入 uid=u1,得 %v", v) } w2 := httptest.NewRecorder() c2, _ := gin.CreateTestContext(w2) c2.Request = httptest.NewRequest("GET", "/x", nil) AuthFromHeaderOrQuery()(c2) if !c2.IsAborted() || w2.Code != 401 { t.Fatalf("无 token 应 401,得 aborted=%v code=%d", c2.IsAborted(), w2.Code) } }