| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567 |
- //go:build unit
- package service
- import (
- "testing"
- "time"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- )
- // ---------------------------------------------------------------------------
- // nextFixedDailyReset
- // ---------------------------------------------------------------------------
- func TestNextFixedDailyReset_BeforeResetHour(t *testing.T) {
- tz := time.UTC
- // 2026-03-14 06:00 UTC, reset hour = 9
- after := time.Date(2026, 3, 14, 6, 0, 0, 0, tz)
- got := nextFixedDailyReset(9, tz, after)
- want := time.Date(2026, 3, 14, 9, 0, 0, 0, tz)
- assert.Equal(t, want, got)
- }
- func TestNextFixedDailyReset_AtResetHour(t *testing.T) {
- tz := time.UTC
- // Exactly at reset hour → should return tomorrow
- after := time.Date(2026, 3, 14, 9, 0, 0, 0, tz)
- got := nextFixedDailyReset(9, tz, after)
- want := time.Date(2026, 3, 15, 9, 0, 0, 0, tz)
- assert.Equal(t, want, got)
- }
- func TestNextFixedDailyReset_AfterResetHour(t *testing.T) {
- tz := time.UTC
- // After reset hour → should return tomorrow
- after := time.Date(2026, 3, 14, 15, 30, 0, 0, tz)
- got := nextFixedDailyReset(9, tz, after)
- want := time.Date(2026, 3, 15, 9, 0, 0, 0, tz)
- assert.Equal(t, want, got)
- }
- func TestNextFixedDailyReset_MidnightReset(t *testing.T) {
- tz := time.UTC
- // Reset at hour 0 (midnight), currently 23:59
- after := time.Date(2026, 3, 14, 23, 59, 0, 0, tz)
- got := nextFixedDailyReset(0, tz, after)
- want := time.Date(2026, 3, 15, 0, 0, 0, 0, tz)
- assert.Equal(t, want, got)
- }
- func TestNextFixedDailyReset_NonUTCTimezone(t *testing.T) {
- tz, err := time.LoadLocation("Asia/Shanghai")
- require.NoError(t, err)
- // 2026-03-14 07:00 UTC = 2026-03-14 15:00 CST, reset hour = 9 (CST)
- after := time.Date(2026, 3, 14, 7, 0, 0, 0, time.UTC)
- got := nextFixedDailyReset(9, tz, after)
- // Already past 9:00 CST today → tomorrow 9:00 CST = 2026-03-15 01:00 UTC
- want := time.Date(2026, 3, 15, 9, 0, 0, 0, tz)
- assert.Equal(t, want, got)
- }
- // ---------------------------------------------------------------------------
- // lastFixedDailyReset
- // ---------------------------------------------------------------------------
- func TestLastFixedDailyReset_BeforeResetHour(t *testing.T) {
- tz := time.UTC
- now := time.Date(2026, 3, 14, 6, 0, 0, 0, tz)
- got := lastFixedDailyReset(9, tz, now)
- // Before today's 9:00 → yesterday 9:00
- want := time.Date(2026, 3, 13, 9, 0, 0, 0, tz)
- assert.Equal(t, want, got)
- }
- func TestLastFixedDailyReset_AtResetHour(t *testing.T) {
- tz := time.UTC
- now := time.Date(2026, 3, 14, 9, 0, 0, 0, tz)
- got := lastFixedDailyReset(9, tz, now)
- // At exactly 9:00 → today 9:00
- want := time.Date(2026, 3, 14, 9, 0, 0, 0, tz)
- assert.Equal(t, want, got)
- }
- func TestLastFixedDailyReset_AfterResetHour(t *testing.T) {
- tz := time.UTC
- now := time.Date(2026, 3, 14, 15, 0, 0, 0, tz)
- got := lastFixedDailyReset(9, tz, now)
- // After 9:00 → today 9:00
- want := time.Date(2026, 3, 14, 9, 0, 0, 0, tz)
- assert.Equal(t, want, got)
- }
- // ---------------------------------------------------------------------------
- // nextFixedWeeklyReset
- // ---------------------------------------------------------------------------
- func TestNextFixedWeeklyReset_TargetDayAhead(t *testing.T) {
- tz := time.UTC
- // 2026-03-14 is Saturday (day=6), target = Monday (day=1), hour = 9
- after := time.Date(2026, 3, 14, 10, 0, 0, 0, tz)
- got := nextFixedWeeklyReset(1, 9, tz, after)
- // Next Monday = 2026-03-16
- want := time.Date(2026, 3, 16, 9, 0, 0, 0, tz)
- assert.Equal(t, want, got)
- }
- func TestNextFixedWeeklyReset_TargetDayToday_BeforeHour(t *testing.T) {
- tz := time.UTC
- // 2026-03-16 is Monday (day=1), target = Monday, hour = 9, before 9:00
- after := time.Date(2026, 3, 16, 6, 0, 0, 0, tz)
- got := nextFixedWeeklyReset(1, 9, tz, after)
- // Today at 9:00
- want := time.Date(2026, 3, 16, 9, 0, 0, 0, tz)
- assert.Equal(t, want, got)
- }
- func TestNextFixedWeeklyReset_TargetDayToday_AtHour(t *testing.T) {
- tz := time.UTC
- // 2026-03-16 is Monday, target = Monday, hour = 9, exactly at 9:00
- after := time.Date(2026, 3, 16, 9, 0, 0, 0, tz)
- got := nextFixedWeeklyReset(1, 9, tz, after)
- // Next Monday at 9:00
- want := time.Date(2026, 3, 23, 9, 0, 0, 0, tz)
- assert.Equal(t, want, got)
- }
- func TestNextFixedWeeklyReset_TargetDayToday_AfterHour(t *testing.T) {
- tz := time.UTC
- // 2026-03-16 is Monday, target = Monday, hour = 9, after 9:00
- after := time.Date(2026, 3, 16, 15, 0, 0, 0, tz)
- got := nextFixedWeeklyReset(1, 9, tz, after)
- // Next Monday at 9:00
- want := time.Date(2026, 3, 23, 9, 0, 0, 0, tz)
- assert.Equal(t, want, got)
- }
- func TestNextFixedWeeklyReset_TargetDayPast(t *testing.T) {
- tz := time.UTC
- // 2026-03-18 is Wednesday (day=3), target = Monday (day=1)
- after := time.Date(2026, 3, 18, 10, 0, 0, 0, tz)
- got := nextFixedWeeklyReset(1, 9, tz, after)
- // Next Monday = 2026-03-23
- want := time.Date(2026, 3, 23, 9, 0, 0, 0, tz)
- assert.Equal(t, want, got)
- }
- func TestNextFixedWeeklyReset_Sunday(t *testing.T) {
- tz := time.UTC
- // 2026-03-14 is Saturday (day=6), target = Sunday (day=0)
- after := time.Date(2026, 3, 14, 10, 0, 0, 0, tz)
- got := nextFixedWeeklyReset(0, 0, tz, after)
- // Next Sunday = 2026-03-15
- want := time.Date(2026, 3, 15, 0, 0, 0, 0, tz)
- assert.Equal(t, want, got)
- }
- // ---------------------------------------------------------------------------
- // lastFixedWeeklyReset
- // ---------------------------------------------------------------------------
- func TestLastFixedWeeklyReset_SameDay_AfterHour(t *testing.T) {
- tz := time.UTC
- // 2026-03-16 is Monday (day=1), target = Monday, hour = 9, now = 15:00
- now := time.Date(2026, 3, 16, 15, 0, 0, 0, tz)
- got := lastFixedWeeklyReset(1, 9, tz, now)
- // Today at 9:00
- want := time.Date(2026, 3, 16, 9, 0, 0, 0, tz)
- assert.Equal(t, want, got)
- }
- func TestLastFixedWeeklyReset_SameDay_BeforeHour(t *testing.T) {
- tz := time.UTC
- // 2026-03-16 is Monday, target = Monday, hour = 9, now = 06:00
- now := time.Date(2026, 3, 16, 6, 0, 0, 0, tz)
- got := lastFixedWeeklyReset(1, 9, tz, now)
- // Last Monday at 9:00 = 2026-03-09
- want := time.Date(2026, 3, 9, 9, 0, 0, 0, tz)
- assert.Equal(t, want, got)
- }
- func TestLastFixedWeeklyReset_DifferentDay(t *testing.T) {
- tz := time.UTC
- // 2026-03-18 is Wednesday (day=3), target = Monday (day=1)
- now := time.Date(2026, 3, 18, 10, 0, 0, 0, tz)
- got := lastFixedWeeklyReset(1, 9, tz, now)
- // Last Monday = 2026-03-16
- want := time.Date(2026, 3, 16, 9, 0, 0, 0, tz)
- assert.Equal(t, want, got)
- }
- // ---------------------------------------------------------------------------
- // isFixedDailyPeriodExpired
- // ---------------------------------------------------------------------------
- func TestIsFixedDailyPeriodExpired_ZeroPeriodStart(t *testing.T) {
- a := &Account{Extra: map[string]any{
- "quota_daily_reset_mode": "fixed",
- "quota_daily_reset_hour": float64(9),
- "quota_reset_timezone": "UTC",
- }}
- assert.True(t, a.isFixedDailyPeriodExpired(time.Time{}))
- }
- func TestIsFixedDailyPeriodExpired_NotExpired(t *testing.T) {
- a := &Account{Extra: map[string]any{
- "quota_daily_reset_mode": "fixed",
- "quota_daily_reset_hour": float64(9),
- "quota_reset_timezone": "UTC",
- }}
- // Anchor periodStart to today's 12:00 UTC: always strictly after today's
- // 09:00 UTC reset (and yesterday's). Using time.Now().Add(-1*time.Minute)
- // is flaky inside the 09:00-09:01 UTC reset window.
- now := time.Now().UTC()
- periodStart := time.Date(now.Year(), now.Month(), now.Day(), 12, 0, 0, 0, time.UTC)
- assert.False(t, a.isFixedDailyPeriodExpired(periodStart))
- }
- func TestIsFixedDailyPeriodExpired_Expired(t *testing.T) {
- a := &Account{Extra: map[string]any{
- "quota_daily_reset_mode": "fixed",
- "quota_daily_reset_hour": float64(9),
- "quota_reset_timezone": "UTC",
- }}
- // Period started 3 days ago → definitely expired
- periodStart := time.Now().Add(-72 * time.Hour)
- assert.True(t, a.isFixedDailyPeriodExpired(periodStart))
- }
- func TestIsFixedDailyPeriodExpired_InvalidTimezone(t *testing.T) {
- a := &Account{Extra: map[string]any{
- "quota_daily_reset_mode": "fixed",
- "quota_daily_reset_hour": float64(9),
- "quota_reset_timezone": "Invalid/Timezone",
- }}
- // Invalid timezone falls back to UTC
- periodStart := time.Now().Add(-72 * time.Hour)
- assert.True(t, a.isFixedDailyPeriodExpired(periodStart))
- }
- // ---------------------------------------------------------------------------
- // isFixedWeeklyPeriodExpired
- // ---------------------------------------------------------------------------
- func TestIsFixedWeeklyPeriodExpired_ZeroPeriodStart(t *testing.T) {
- a := &Account{Extra: map[string]any{
- "quota_weekly_reset_mode": "fixed",
- "quota_weekly_reset_day": float64(1),
- "quota_weekly_reset_hour": float64(9),
- "quota_reset_timezone": "UTC",
- }}
- assert.True(t, a.isFixedWeeklyPeriodExpired(time.Time{}))
- }
- func TestIsFixedWeeklyPeriodExpired_NotExpired(t *testing.T) {
- a := &Account{Extra: map[string]any{
- "quota_weekly_reset_mode": "fixed",
- "quota_weekly_reset_day": float64(1),
- "quota_weekly_reset_hour": float64(9),
- "quota_reset_timezone": "UTC",
- }}
- // Anchor periodStart to today's 12:00 UTC: always strictly after the most
- // recent Monday 09:00 UTC reset, regardless of which weekday/hour the test
- // runs. Using time.Now().Add(-1*time.Minute) is flaky inside the
- // Monday 09:00-09:01 UTC reset window.
- now := time.Now().UTC()
- periodStart := time.Date(now.Year(), now.Month(), now.Day(), 12, 0, 0, 0, time.UTC)
- assert.False(t, a.isFixedWeeklyPeriodExpired(periodStart))
- }
- func TestIsFixedWeeklyPeriodExpired_Expired(t *testing.T) {
- a := &Account{Extra: map[string]any{
- "quota_weekly_reset_mode": "fixed",
- "quota_weekly_reset_day": float64(1),
- "quota_weekly_reset_hour": float64(9),
- "quota_reset_timezone": "UTC",
- }}
- // Period started 10 days ago → definitely expired
- periodStart := time.Now().Add(-240 * time.Hour)
- assert.True(t, a.isFixedWeeklyPeriodExpired(periodStart))
- }
- // ---------------------------------------------------------------------------
- // ValidateQuotaResetConfig
- // ---------------------------------------------------------------------------
- func TestValidateQuotaResetConfig_NilExtra(t *testing.T) {
- assert.NoError(t, ValidateQuotaResetConfig(nil))
- }
- func TestValidateQuotaResetConfig_EmptyExtra(t *testing.T) {
- assert.NoError(t, ValidateQuotaResetConfig(map[string]any{}))
- }
- func TestValidateQuotaResetConfig_ValidFixed(t *testing.T) {
- extra := map[string]any{
- "quota_daily_reset_mode": "fixed",
- "quota_daily_reset_hour": float64(9),
- "quota_weekly_reset_mode": "fixed",
- "quota_weekly_reset_day": float64(1),
- "quota_weekly_reset_hour": float64(0),
- "quota_reset_timezone": "Asia/Shanghai",
- }
- assert.NoError(t, ValidateQuotaResetConfig(extra))
- }
- func TestValidateQuotaResetConfig_ValidRolling(t *testing.T) {
- extra := map[string]any{
- "quota_daily_reset_mode": "rolling",
- "quota_weekly_reset_mode": "rolling",
- }
- assert.NoError(t, ValidateQuotaResetConfig(extra))
- }
- func TestValidateQuotaResetConfig_InvalidTimezone(t *testing.T) {
- extra := map[string]any{
- "quota_reset_timezone": "Not/A/Timezone",
- }
- err := ValidateQuotaResetConfig(extra)
- require.Error(t, err)
- assert.Contains(t, err.Error(), "quota_reset_timezone")
- }
- func TestValidateQuotaResetConfig_InvalidDailyMode(t *testing.T) {
- extra := map[string]any{
- "quota_daily_reset_mode": "invalid",
- }
- err := ValidateQuotaResetConfig(extra)
- require.Error(t, err)
- assert.Contains(t, err.Error(), "quota_daily_reset_mode")
- }
- func TestValidateQuotaResetConfig_InvalidDailyHour_TooHigh(t *testing.T) {
- extra := map[string]any{
- "quota_daily_reset_hour": float64(24),
- }
- err := ValidateQuotaResetConfig(extra)
- require.Error(t, err)
- assert.Contains(t, err.Error(), "quota_daily_reset_hour")
- }
- func TestValidateQuotaResetConfig_InvalidDailyHour_Negative(t *testing.T) {
- extra := map[string]any{
- "quota_daily_reset_hour": float64(-1),
- }
- err := ValidateQuotaResetConfig(extra)
- require.Error(t, err)
- assert.Contains(t, err.Error(), "quota_daily_reset_hour")
- }
- func TestValidateQuotaResetConfig_InvalidWeeklyMode(t *testing.T) {
- extra := map[string]any{
- "quota_weekly_reset_mode": "unknown",
- }
- err := ValidateQuotaResetConfig(extra)
- require.Error(t, err)
- assert.Contains(t, err.Error(), "quota_weekly_reset_mode")
- }
- func TestValidateQuotaResetConfig_InvalidWeeklyDay_TooHigh(t *testing.T) {
- extra := map[string]any{
- "quota_weekly_reset_day": float64(7),
- }
- err := ValidateQuotaResetConfig(extra)
- require.Error(t, err)
- assert.Contains(t, err.Error(), "quota_weekly_reset_day")
- }
- func TestValidateQuotaResetConfig_InvalidWeeklyDay_Negative(t *testing.T) {
- extra := map[string]any{
- "quota_weekly_reset_day": float64(-1),
- }
- err := ValidateQuotaResetConfig(extra)
- require.Error(t, err)
- assert.Contains(t, err.Error(), "quota_weekly_reset_day")
- }
- func TestValidateQuotaResetConfig_InvalidWeeklyHour(t *testing.T) {
- extra := map[string]any{
- "quota_weekly_reset_hour": float64(25),
- }
- err := ValidateQuotaResetConfig(extra)
- require.Error(t, err)
- assert.Contains(t, err.Error(), "quota_weekly_reset_hour")
- }
- func TestValidateQuotaResetConfig_BoundaryValues(t *testing.T) {
- // All boundary values should be valid
- extra := map[string]any{
- "quota_daily_reset_hour": float64(23),
- "quota_weekly_reset_day": float64(0), // Sunday
- "quota_weekly_reset_hour": float64(0),
- "quota_reset_timezone": "UTC",
- }
- assert.NoError(t, ValidateQuotaResetConfig(extra))
- extra2 := map[string]any{
- "quota_daily_reset_hour": float64(0),
- "quota_weekly_reset_day": float64(6), // Saturday
- "quota_weekly_reset_hour": float64(23),
- }
- assert.NoError(t, ValidateQuotaResetConfig(extra2))
- }
- // ---------------------------------------------------------------------------
- // NormalizeFixedQuotaWindows
- // ---------------------------------------------------------------------------
- func TestNormalizeFixedQuotaWindows_ClearsExpiredWeeklyWindow(t *testing.T) {
- now := time.Now().UTC()
- daysSinceMonday := (int(now.Weekday()) + 6) % 7
- currentWeekStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC).AddDate(0, 0, -daysSinceMonday)
- staleStart := currentWeekStart.Add(-24 * time.Hour)
- extra := map[string]any{
- "quota_weekly_limit": 500.0,
- "quota_weekly_used": 76.0,
- "quota_weekly_start": staleStart.Format(time.RFC3339),
- "quota_weekly_reset_mode": "fixed",
- "quota_weekly_reset_day": float64(1),
- "quota_weekly_reset_hour": float64(0),
- "quota_reset_timezone": "UTC",
- }
- NormalizeFixedQuotaWindows(extra)
- assert.Equal(t, 0.0, extra["quota_weekly_used"])
- assert.Equal(t, currentWeekStart.Format(time.RFC3339), extra["quota_weekly_start"])
- }
- func TestNormalizeFixedQuotaWindows_KeepsActiveWeeklyWindow(t *testing.T) {
- now := time.Now().UTC()
- daysSinceMonday := (int(now.Weekday()) + 6) % 7
- currentWeekStart := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC).AddDate(0, 0, -daysSinceMonday)
- extra := map[string]any{
- "quota_weekly_limit": 500.0,
- "quota_weekly_used": 76.0,
- "quota_weekly_start": currentWeekStart.Format(time.RFC3339),
- "quota_weekly_reset_mode": "fixed",
- "quota_weekly_reset_day": float64(1),
- "quota_weekly_reset_hour": float64(0),
- "quota_reset_timezone": "UTC",
- }
- NormalizeFixedQuotaWindows(extra)
- assert.Equal(t, 76.0, extra["quota_weekly_used"])
- assert.Equal(t, currentWeekStart.Format(time.RFC3339), extra["quota_weekly_start"])
- }
- // ---------------------------------------------------------------------------
- // ComputeQuotaResetAt
- // ---------------------------------------------------------------------------
- func TestComputeQuotaResetAt_RollingMode_NoResetAt(t *testing.T) {
- extra := map[string]any{
- "quota_daily_reset_mode": "rolling",
- "quota_weekly_reset_mode": "rolling",
- }
- ComputeQuotaResetAt(extra)
- _, hasDailyResetAt := extra["quota_daily_reset_at"]
- _, hasWeeklyResetAt := extra["quota_weekly_reset_at"]
- assert.False(t, hasDailyResetAt, "rolling mode should not set quota_daily_reset_at")
- assert.False(t, hasWeeklyResetAt, "rolling mode should not set quota_weekly_reset_at")
- }
- func TestComputeQuotaResetAt_RollingMode_ClearsExistingResetAt(t *testing.T) {
- extra := map[string]any{
- "quota_daily_reset_mode": "rolling",
- "quota_weekly_reset_mode": "rolling",
- "quota_daily_reset_at": "2026-03-14T09:00:00Z",
- "quota_weekly_reset_at": "2026-03-16T09:00:00Z",
- }
- ComputeQuotaResetAt(extra)
- _, hasDailyResetAt := extra["quota_daily_reset_at"]
- _, hasWeeklyResetAt := extra["quota_weekly_reset_at"]
- assert.False(t, hasDailyResetAt, "rolling mode should remove quota_daily_reset_at")
- assert.False(t, hasWeeklyResetAt, "rolling mode should remove quota_weekly_reset_at")
- }
- func TestComputeQuotaResetAt_FixedDaily_SetsResetAt(t *testing.T) {
- extra := map[string]any{
- "quota_daily_reset_mode": "fixed",
- "quota_daily_reset_hour": float64(9),
- "quota_reset_timezone": "UTC",
- }
- ComputeQuotaResetAt(extra)
- resetAtStr, ok := extra["quota_daily_reset_at"].(string)
- require.True(t, ok, "quota_daily_reset_at should be set")
- resetAt, err := time.Parse(time.RFC3339, resetAtStr)
- require.NoError(t, err)
- // Reset time should be in the future
- assert.True(t, resetAt.After(time.Now()), "reset_at should be in the future")
- // Reset hour should be 9 UTC
- assert.Equal(t, 9, resetAt.UTC().Hour())
- }
- func TestComputeQuotaResetAt_FixedWeekly_SetsResetAt(t *testing.T) {
- extra := map[string]any{
- "quota_weekly_reset_mode": "fixed",
- "quota_weekly_reset_day": float64(1), // Monday
- "quota_weekly_reset_hour": float64(0),
- "quota_reset_timezone": "UTC",
- }
- ComputeQuotaResetAt(extra)
- resetAtStr, ok := extra["quota_weekly_reset_at"].(string)
- require.True(t, ok, "quota_weekly_reset_at should be set")
- resetAt, err := time.Parse(time.RFC3339, resetAtStr)
- require.NoError(t, err)
- // Reset time should be in the future
- assert.True(t, resetAt.After(time.Now()), "reset_at should be in the future")
- // Reset day should be Monday
- assert.Equal(t, time.Monday, resetAt.UTC().Weekday())
- }
- func TestComputeQuotaResetAt_FixedDaily_WithTimezone(t *testing.T) {
- tz, err := time.LoadLocation("Asia/Shanghai")
- require.NoError(t, err)
- extra := map[string]any{
- "quota_daily_reset_mode": "fixed",
- "quota_daily_reset_hour": float64(9),
- "quota_reset_timezone": "Asia/Shanghai",
- }
- ComputeQuotaResetAt(extra)
- resetAtStr, ok := extra["quota_daily_reset_at"].(string)
- require.True(t, ok)
- resetAt, err := time.Parse(time.RFC3339, resetAtStr)
- require.NoError(t, err)
- // In Shanghai timezone, the hour should be 9
- assert.Equal(t, 9, resetAt.In(tz).Hour())
- }
- func TestComputeQuotaResetAt_DefaultTimezone(t *testing.T) {
- extra := map[string]any{
- "quota_daily_reset_mode": "fixed",
- "quota_daily_reset_hour": float64(12),
- }
- ComputeQuotaResetAt(extra)
- resetAtStr, ok := extra["quota_daily_reset_at"].(string)
- require.True(t, ok)
- resetAt, err := time.Parse(time.RFC3339, resetAtStr)
- require.NoError(t, err)
- // Default timezone is UTC
- assert.Equal(t, 12, resetAt.UTC().Hour())
- }
- func TestComputeQuotaResetAt_InvalidHour_ClampedToZero(t *testing.T) {
- extra := map[string]any{
- "quota_daily_reset_mode": "fixed",
- "quota_daily_reset_hour": float64(99),
- "quota_reset_timezone": "UTC",
- }
- ComputeQuotaResetAt(extra)
- resetAtStr, ok := extra["quota_daily_reset_at"].(string)
- require.True(t, ok)
- resetAt, err := time.Parse(time.RFC3339, resetAtStr)
- require.NoError(t, err)
- // Invalid hour → clamped to 0
- assert.Equal(t, 0, resetAt.UTC().Hour())
- }
|