package autocleanup import ( "sync" "testing" "github.com/stretchr/testify/require" ) type memoryStore struct { mu sync.Mutex configs map[string]Config } func newMemoryStore(configs map[string]Config) *memoryStore { if configs == nil { configs = make(map[string]Config) } return &memoryStore{configs: configs} } func (s *memoryStore) Get(channelID string) (*Config, error) { s.mu.Lock() defer s.mu.Unlock() config, ok := s.configs[channelID] if !ok || config.OffsetDays <= 0 { return nil, nil } config.ChannelID = channelID return &config, nil } func (s *memoryStore) Set(channelID string, offsetDays int) error { s.mu.Lock() defer s.mu.Unlock() s.configs[channelID] = Config{ ChannelID: channelID, OffsetDays: offsetDays, } return nil } func (s *memoryStore) Delete(channelID string) error { s.mu.Lock() defer s.mu.Unlock() delete(s.configs, channelID) return nil } func (s *memoryStore) List() ([]Config, error) { s.mu.Lock() defer s.mu.Unlock() configs := make([]Config, 0, len(s.configs)) for channelID, config := range s.configs { if config.OffsetDays <= 0 { continue } config.ChannelID = channelID configs = append(configs, config) } return configs, nil } type cleanupCall struct { channelID string offsetDays int } func TestRunnerOnlyCleansConfiguredChannels(t *testing.T) { store := newMemoryStore(map[string]Config{ "channel-a": {OffsetDays: 30}, "channel-b": {OffsetDays: 7}, }) var calls []cleanupCall runner := &Runner{ store: store, cleanup: func(channelID string, offsetDays int) (int, error) { calls = append(calls, cleanupCall{channelID: channelID, offsetDays: offsetDays}) return 1, nil }, } runner.Run() require.Len(t, calls, 2) require.ElementsMatch(t, []cleanupCall{ {channelID: "channel-a", offsetDays: 30}, {channelID: "channel-b", offsetDays: 7}, }, calls) } func TestRunnerDoesNothingWhenNoConfiguredChannels(t *testing.T) { store := newMemoryStore(nil) called := false runner := &Runner{ store: store, cleanup: func(channelID string, offsetDays int) (int, error) { called = true return 0, nil }, } runner.Run() require.False(t, called) } func TestRunnerSkipsDisabledChannels(t *testing.T) { store := newMemoryStore(map[string]Config{ "enabled-channel": {OffsetDays: 14}, "disabled-channel": {OffsetDays: 0}, }) var cleanedChannels []string runner := &Runner{ store: store, cleanup: func(channelID string, offsetDays int) (int, error) { cleanedChannels = append(cleanedChannels, channelID) return 0, nil }, } runner.Run() require.Equal(t, []string{"enabled-channel"}, cleanedChannels) } func TestRunnerUsesConfiguredOffsetDays(t *testing.T) { store := newMemoryStore(map[string]Config{ "channel-a": {OffsetDays: 90}, }) var offsetDays int runner := &Runner{ store: store, cleanup: func(channelID string, days int) (int, error) { offsetDays = days return 0, nil }, } runner.Run() require.Equal(t, 90, offsetDays) } func TestRunnerNeverCleansUnconfiguredChannel(t *testing.T) { store := newMemoryStore(map[string]Config{ "configured": {OffsetDays: 10}, }) cleaned := make(map[string]bool) runner := &Runner{ store: store, cleanup: func(channelID string, offsetDays int) (int, error) { cleaned[channelID] = true return 0, nil }, } runner.Run() require.True(t, cleaned["configured"]) require.False(t, cleaned["unconfigured"]) require.False(t, cleaned["another-channel"]) }