hyapp-server/server/admin/internal/cache/redis_fixed_window_test.go

35 lines
1.4 KiB
Go

package cache
import (
"context"
"errors"
"strings"
"testing"
"time"
)
func TestConsumeFixedWindowFailsClosedWithoutRedis(t *testing.T) {
_, err := (*Redis)(nil).ConsumeFixedWindow(context.Background(), time.Minute, []FixedWindowRule{{Key: "rate:{external-login}:system", Limit: 300}})
if !errors.Is(err, ErrRedisUnavailable) {
t.Fatalf("error = %v, want ErrRedisUnavailable", err)
}
}
func TestFixedWindowLuaConsumesAllKeysWithoutRenewingExistingTTL(t *testing.T) {
// These source-level invariants protect the security semantics even when unit
// tests run without a Redis daemon: all keys increment before the one final
// return, and PEXPIRE remains inside count==1 so rejected requests never slide TTL.
if strings.Count(fixedWindowScript, `redis.call("INCR"`) != 1 {
t.Fatalf("fixed-window script must increment through one loop: %s", fixedWindowScript)
}
if !strings.Contains(fixedWindowScript, `if count == 1 then`) || !strings.Contains(fixedWindowScript, `redis.call("PEXPIRE"`) {
t.Fatal("fixed-window script must assign expiry only on first increment")
}
if strings.Count(fixedWindowScript, "return {") != 1 {
t.Fatal("fixed-window script must not return early before consuming all keys")
}
if strings.Index(fixedWindowScript, `redis.call("INCR"`) > strings.Index(fixedWindowScript, `if count > limit then`) {
t.Fatal("fixed-window script must increment before deciding")
}
}