Files
graphql-monitoring-proxy/ratelimit_units_test.go
T
lukaszraczylo c128a0f4d9 fix(ratelimit): count Req per Interval, not per second
The sustained gate compared requests per second with Req, which is a count per Interval. An interval of one minute with req 10 allowed 600 requests. The gate now compares the count in the interval with Req. One-second intervals behave as before. A burst at or above req has no effect, because the sustained gate always binds first.
2026-11-03 00:07:57 +00:00

45 lines
1.2 KiB
Go

package main
import (
"testing"
"time"
libpack_logger "github.com/lukaszraczylo/graphql-monitoring-proxy/logging"
)
func setupRateLimitCfg() {
cfg = &config{}
parseConfig()
cfg.Logger = libpack_logger.New()
}
// Pins theorems/Theorems/RateLimitUnits.lean: Req counts requests per Interval, not per second.
func TestCheckRateLimit_ReqIsPerInterval(t *testing.T) {
const req = 3
setupRateLimitCfg()
rc := newBurstTestRoleConfig(time.Minute, req, 0)
for i := 1; i <= req; i++ {
if !checkRateLimit("u", "r", rc, "") {
t.Fatalf("request %d denied, want allowed (Req=%d per minute)", i, req)
}
}
if checkRateLimit("u", "r", rc, "") {
t.Fatalf("request %d allowed, want denied: Req=%d per minute", req+1, req)
}
}
// With Burst >= Req the burst gate never rejects what the sustained gate admits.
func TestCheckRateLimit_BurstAboveReqIsNoOp(t *testing.T) {
const req, burst = 3, 6
setupRateLimitCfg()
rc := newBurstTestRoleConfig(time.Minute, req, burst)
for i := 1; i <= req; i++ {
if !checkRateLimit("u", "r", rc, "") {
t.Fatalf("request %d denied", i)
}
}
if checkRateLimit("u", "r", rc, "") {
t.Fatalf("request %d allowed, want denied by the sustained gate", req+1)
}
}