172 lines
6.2 KiB
Go
172 lines
6.2 KiB
Go
//go:build unit
|
|||
|
|
|
||
|
|
package service
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"github.com/Wei-Shaw/sub2api/internal/config"
|
||
|
|
"github.com/stretchr/testify/require"
|
||
|
|
)
|
||
|
|
|
||
|
|
func newSettingServiceForPlatformThresholdTest(seed map[string]string) *SettingService {
|
||
|
|
accountSchedulingThresholdsSF.Forget(SettingKeyAccountSchedulingThresholds)
|
||
|
|
accountSchedulingThresholdsCache.Store(&cachedAccountSchedulingThresholds{})
|
||
|
|
repo := newMockSettingRepo()
|
||
|
|
for k, v := range seed {
|
||
|
|
repo.data[k] = v
|
||
|
|
}
|
||
|
|
return NewSettingService(repo, &config.Config{})
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestPlatformSchedulingThresholds_RoundTrip_DefaultsAndStoredValues(t *testing.T) {
|
||
|
|
svc := newSettingServiceForPlatformThresholdTest(nil)
|
||
|
|
|
||
|
|
got := svc.parseSettings(map[string]string{})
|
||
|
|
require.Equal(t, map[string]int{
|
||
|
|
PlatformOpenAI: 100,
|
||
|
|
PlatformAnthropic: 100,
|
||
|
|
PlatformGrok: 100,
|
||
|
|
}, got.AccountSchedulingThresholds)
|
||
|
|
|
||
|
|
got = svc.parseSettings(map[string]string{
|
||
|
|
SettingKeyAccountSchedulingThresholds: `{"openai":91,"grok":77,"gemini":85,"kiro":99}`,
|
||
|
|
})
|
||
|
|
require.Equal(t, 91, got.AccountSchedulingThresholds[PlatformOpenAI])
|
||
|
|
require.Equal(t, 100, got.AccountSchedulingThresholds[PlatformAnthropic])
|
||
|
|
require.Equal(t, 77, got.AccountSchedulingThresholds[PlatformGrok])
|
||
|
|
require.NotContains(t, got.AccountSchedulingThresholds, PlatformGemini)
|
||
|
|
require.NotContains(t, got.AccountSchedulingThresholds, "kiro")
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBuildSystemSettingsUpdates_PersistsAccountSchedulingThresholds(t *testing.T) {
|
||
|
|
svc := newSettingServiceForPlatformThresholdTest(nil)
|
||
|
|
|
||
|
|
updates, err := svc.buildSystemSettingsUpdates(context.Background(), &SystemSettings{
|
||
|
|
AccountSchedulingThresholds: map[string]int{
|
||
|
|
PlatformOpenAI: 91,
|
||
|
|
PlatformAnthropic: 88,
|
||
|
|
PlatformGrok: 77,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
require.NoError(t, err)
|
||
|
|
require.JSONEq(t, `{"openai":91,"anthropic":88,"grok":77}`, updates[SettingKeyAccountSchedulingThresholds])
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestValidateAndNormalizeAccountSchedulingThresholds_FillsMissingPlatforms(t *testing.T) {
|
||
|
|
normalized, err := validateAndNormalizeAccountSchedulingThresholds(map[string]int{
|
||
|
|
PlatformOpenAI: 91,
|
||
|
|
})
|
||
|
|
require.NoError(t, err)
|
||
|
|
require.Equal(t, 91, normalized[PlatformOpenAI])
|
||
|
|
require.Equal(t, 100, normalized[PlatformAnthropic])
|
||
|
|
require.Equal(t, 100, normalized[PlatformGrok])
|
||
|
|
require.NotContains(t, normalized, PlatformGemini)
|
||
|
|
require.NotContains(t, normalized, "kiro")
|
||
|
|
require.NotContains(t, normalized, PlatformAntigravity)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestValidateAndNormalizeAccountSchedulingThresholds_RejectsUnsupportedPlatforms(t *testing.T) {
|
||
|
|
_, err := validateAndNormalizeAccountSchedulingThresholds(map[string]int{
|
||
|
|
PlatformGemini: 85,
|
||
|
|
})
|
||
|
|
require.Error(t, err)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestUpdateSettings_StoresAccountSchedulingThresholds(t *testing.T) {
|
||
|
|
svc := newSettingServiceForPlatformThresholdTest(nil)
|
||
|
|
|
||
|
|
err := svc.UpdateSettings(context.Background(), &SystemSettings{
|
||
|
|
AccountSchedulingThresholds: map[string]int{
|
||
|
|
PlatformOpenAI: 92,
|
||
|
|
PlatformAnthropic: 89,
|
||
|
|
PlatformGrok: 76,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
require.NoError(t, err)
|
||
|
|
|
||
|
|
got := svc.parseSettings(map[string]string{
|
||
|
|
SettingKeyAccountSchedulingThresholds: svc.settingRepo.(*mockSettingRepo).data[SettingKeyAccountSchedulingThresholds],
|
||
|
|
})
|
||
|
|
require.Equal(t, 92, got.AccountSchedulingThresholds[PlatformOpenAI])
|
||
|
|
require.Equal(t, 89, got.AccountSchedulingThresholds[PlatformAnthropic])
|
||
|
|
require.Equal(t, 76, got.AccountSchedulingThresholds[PlatformGrok])
|
||
|
|
require.NotContains(t, got.AccountSchedulingThresholds, "kiro")
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGetAccountSchedulingThresholds_ReadsStoredValue(t *testing.T) {
|
||
|
|
svc := newSettingServiceForPlatformThresholdTest(map[string]string{
|
||
|
|
SettingKeyAccountSchedulingThresholds: `{"openai":93,"grok":88,"kiro":87}`,
|
||
|
|
})
|
||
|
|
|
||
|
|
got := svc.GetAccountSchedulingThresholds(context.Background())
|
||
|
|
|
||
|
|
require.Equal(t, 93, got[PlatformOpenAI])
|
||
|
|
require.Equal(t, 100, got[PlatformAnthropic])
|
||
|
|
require.Equal(t, 88, got[PlatformGrok])
|
||
|
|
require.NotContains(t, got, "kiro")
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGetAccountSchedulingThresholds_MissingSettingUsesDefaultsAndNormalCacheTTL(t *testing.T) {
|
||
|
|
svc := newSettingServiceForPlatformThresholdTest(nil)
|
||
|
|
repo := svc.settingRepo.(*mockSettingRepo)
|
||
|
|
repo.getValueErr = ErrSettingNotFound
|
||
|
|
|
||
|
|
got := svc.GetAccountSchedulingThresholds(context.Background())
|
||
|
|
require.Equal(t, defaultAccountSchedulingThresholds(), got)
|
||
|
|
require.Equal(t, 1, repo.getValueCalls)
|
||
|
|
|
||
|
|
repo.data[SettingKeyAccountSchedulingThresholds] = `{"openai":91}`
|
||
|
|
got = svc.GetAccountSchedulingThresholds(context.Background())
|
||
|
|
require.Equal(t, 100, got[PlatformOpenAI], "missing-setting defaults should remain cached for the normal TTL")
|
||
|
|
require.Equal(t, 1, repo.getValueCalls)
|
||
|
|
|
||
|
|
cached, ok := accountSchedulingThresholdsCache.Load().(*cachedAccountSchedulingThresholds)
|
||
|
|
require.True(t, ok)
|
||
|
|
require.Greater(t, cached.expiresAt, time.Now().Add(accountSchedulingThresholdsCacheTTL-time.Second).UnixNano())
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestUpdateSettings_OmittedAccountSchedulingThresholdsDoesNotCacheDefaults(t *testing.T) {
|
||
|
|
svc := newSettingServiceForPlatformThresholdTest(map[string]string{
|
||
|
|
SettingKeyAccountSchedulingThresholds: `{"openai":85,"grok":88,"kiro":87}`,
|
||
|
|
})
|
||
|
|
|
||
|
|
err := svc.UpdateSettings(context.Background(), &SystemSettings{
|
||
|
|
FrontendURL: "https://example.test",
|
||
|
|
})
|
||
|
|
require.NoError(t, err)
|
||
|
|
|
||
|
|
got := svc.GetAccountSchedulingThresholds(context.Background())
|
||
|
|
require.Equal(t, 85, got[PlatformOpenAI])
|
||
|
|
require.Equal(t, 88, got[PlatformGrok])
|
||
|
|
require.NotContains(t, got, "kiro")
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestAccountSchedulingThresholds_InvalidStoredValueUsesSameDefaultsInSettingsAndCache(t *testing.T) {
|
||
|
|
svc := newSettingServiceForPlatformThresholdTest(map[string]string{
|
||
|
|
SettingKeyAccountSchedulingThresholds: `{"openai":0,"grok":88,"kiro":87}`,
|
||
|
|
})
|
||
|
|
|
||
|
|
settings := svc.parseSettings(map[string]string{
|
||
|
|
SettingKeyAccountSchedulingThresholds: `{"openai":0,"grok":88,"kiro":87}`,
|
||
|
|
})
|
||
|
|
cached := svc.GetAccountSchedulingThresholds(context.Background())
|
||
|
|
|
||
|
|
require.Equal(t, settings.AccountSchedulingThresholds, cached)
|
||
|
|
require.Equal(t, 100, cached[PlatformOpenAI])
|
||
|
|
require.Equal(t, 88, cached[PlatformGrok])
|
||
|
|
require.NotContains(t, cached, "kiro")
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGetAccountSchedulingThresholds_NilRepoReturnsDefaults(t *testing.T) {
|
||
|
|
svc := &SettingService{}
|
||
|
|
got := svc.GetAccountSchedulingThresholds(context.Background())
|
||
|
|
require.Equal(t, map[string]int{
|
||
|
|
PlatformOpenAI: 100,
|
||
|
|
PlatformAnthropic: 100,
|
||
|
|
PlatformGrok: 100,
|
||
|
|
}, got)
|
||
|
|
}
|