package worker import ( "context" "sync/atomic" "testing" "time" "github.com/gojuno/minimock/v3" "github.com/stretchr/testify/suite" "go.uber.org/zap" "git.techease.ru/Smart-search/smart-search-back/internal/mocks" ) type WorkerSuite struct { suite.Suite ctx context.Context cancel context.CancelFunc ctrl *minimock.Controller logger *zap.Logger } func TestWorkerSuite(t *testing.T) { suite.Run(t, new(WorkerSuite)) } func (s *WorkerSuite) SetupTest() { s.ctx, s.cancel = context.WithCancel(context.Background()) s.ctrl = minimock.NewController(s.T()) s.logger = zap.NewNop() } func (s *WorkerSuite) TearDownTest() { if s.cancel != nil { s.cancel() } } func (s *WorkerSuite) TestSessionCleaner_StartStop() { var callCount int32 sessionRepo := mocks.NewSessionRepositoryMock(s.ctrl) sessionRepo.DeleteExpiredMock.Set(func(_ context.Context) (int, error) { atomic.AddInt32(&callCount, 1) return 5, nil }) cleaner := NewSessionCleaner(s.ctx, sessionRepo, s.logger) cleaner.Start() time.Sleep(50 * time.Millisecond) cleaner.Stop() s.GreaterOrEqual(int(atomic.LoadInt32(&callCount)), 1, "DeleteExpired должен быть вызван хотя бы раз при старте") } func (s *WorkerSuite) TestSessionCleaner_ContextCancellation() { var callCount int32 sessionRepo := mocks.NewSessionRepositoryMock(s.ctrl) sessionRepo.DeleteExpiredMock.Set(func(_ context.Context) (int, error) { atomic.AddInt32(&callCount, 1) return 0, nil }) cleaner := NewSessionCleaner(s.ctx, sessionRepo, s.logger) cleaner.Start() time.Sleep(50 * time.Millisecond) s.cancel() time.Sleep(50 * time.Millisecond) s.GreaterOrEqual(int(atomic.LoadInt32(&callCount)), 1, "DeleteExpired должен быть вызван хотя бы раз") } func (s *WorkerSuite) TestInviteCleaner_StartStop() { var callCount int32 inviteRepo := mocks.NewInviteRepositoryMock(s.ctrl) inviteRepo.DeactivateExpiredMock.Set(func(_ context.Context) (int, error) { atomic.AddInt32(&callCount, 1) return 3, nil }) cleaner := NewInviteCleaner(s.ctx, inviteRepo, s.logger) cleaner.Start() time.Sleep(50 * time.Millisecond) cleaner.Stop() s.GreaterOrEqual(int(atomic.LoadInt32(&callCount)), 1, "DeactivateExpired должен быть вызван хотя бы раз при старте") } func (s *WorkerSuite) TestInviteCleaner_ContextCancellation() { var callCount int32 inviteRepo := mocks.NewInviteRepositoryMock(s.ctrl) inviteRepo.DeactivateExpiredMock.Set(func(_ context.Context) (int, error) { atomic.AddInt32(&callCount, 1) return 0, nil }) cleaner := NewInviteCleaner(s.ctx, inviteRepo, s.logger) cleaner.Start() time.Sleep(50 * time.Millisecond) s.cancel() time.Sleep(50 * time.Millisecond) s.GreaterOrEqual(int(atomic.LoadInt32(&callCount)), 1, "DeactivateExpired должен быть вызван хотя бы раз") } func (s *WorkerSuite) TestSessionCleaner_ConcurrentStops() { sessionRepo := mocks.NewSessionRepositoryMock(s.ctrl) sessionRepo.DeleteExpiredMock.Set(func(_ context.Context) (int, error) { return 0, nil }) cleaner := NewSessionCleaner(s.ctx, sessionRepo, s.logger) cleaner.Start() time.Sleep(50 * time.Millisecond) done := make(chan struct{}) for i := 0; i < 5; i++ { go func() { cleaner.Stop() }() } go func() { time.Sleep(100 * time.Millisecond) close(done) }() <-done } func (s *WorkerSuite) TestInviteCleaner_ConcurrentStops() { inviteRepo := mocks.NewInviteRepositoryMock(s.ctrl) inviteRepo.DeactivateExpiredMock.Set(func(_ context.Context) (int, error) { return 0, nil }) cleaner := NewInviteCleaner(s.ctx, inviteRepo, s.logger) cleaner.Start() time.Sleep(50 * time.Millisecond) done := make(chan struct{}) for i := 0; i < 5; i++ { go func() { cleaner.Stop() }() } go func() { time.Sleep(100 * time.Millisecond) close(done) }() <-done } func (s *WorkerSuite) TestSessionCleaner_MultipleStartStop() { var callCount int32 sessionRepo := mocks.NewSessionRepositoryMock(s.ctrl) sessionRepo.DeleteExpiredMock.Set(func(_ context.Context) (int, error) { atomic.AddInt32(&callCount, 1) return 2, nil }) cleaner := NewSessionCleaner(s.ctx, sessionRepo, s.logger) for i := 0; i < 3; i++ { cleaner.Start() time.Sleep(20 * time.Millisecond) cleaner.Stop() } s.GreaterOrEqual(int(atomic.LoadInt32(&callCount)), 3, "DeleteExpired должен быть вызван минимум 3 раза") } func (s *WorkerSuite) TestInviteCleaner_MultipleStartStop() { var callCount int32 inviteRepo := mocks.NewInviteRepositoryMock(s.ctrl) inviteRepo.DeactivateExpiredMock.Set(func(_ context.Context) (int, error) { atomic.AddInt32(&callCount, 1) return 1, nil }) cleaner := NewInviteCleaner(s.ctx, inviteRepo, s.logger) for i := 0; i < 3; i++ { cleaner.Start() time.Sleep(20 * time.Millisecond) cleaner.Stop() } s.GreaterOrEqual(int(atomic.LoadInt32(&callCount)), 3, "DeactivateExpired должен быть вызван минимум 3 раза") }