package scheduler import ( "context" "errors" "sync/atomic" "testing" "time" ) func TestRunOnce(t *testing.T) { var calls atomic.Int32 s := New(0, func(ctx context.Context) error { calls.Add(1) return nil }) if err := s.Run(context.Background()); err != nil { t.Fatalf("Run: %v", err) } if got := calls.Load(); got != 1 { t.Errorf("run called %d times, want 1", got) } } func TestRunPeriodic(t *testing.T) { var calls atomic.Int32 s := New(10*time.Millisecond, func(ctx context.Context) error { calls.Add(1) return nil }) ctx, cancel := context.WithCancel(context.Background()) done := make(chan error, 1) go func() { done <- s.Run(ctx) }() time.Sleep(55 * time.Millisecond) cancel() if err := <-done; err != nil { t.Fatalf("Run: %v", err) } if got := calls.Load(); got < 3 { t.Errorf("run called %d times, want >= 3", got) } } func TestRunStopsOnError(t *testing.T) { var calls atomic.Int32 wantErr := errors.New("boom") s := New(5*time.Millisecond, func(ctx context.Context) error { n := calls.Add(1) if n == 2 { return wantErr } return nil }) if err := s.Run(context.Background()); !errors.Is(err, wantErr) { t.Fatalf("Run() error = %v, want %v", err, wantErr) } if got := calls.Load(); got != 2 { t.Errorf("run called %d times, want 2", got) } } func TestRunCancelledBeforeStart(t *testing.T) { var calls atomic.Int32 s := New(time.Second, func(ctx context.Context) error { calls.Add(1) return nil }) ctx, cancel := context.WithCancel(context.Background()) cancel() if err := s.Run(ctx); err != nil { t.Fatalf("Run: %v", err) } if got := calls.Load(); got != 0 { t.Errorf("run called %d times, want 0", got) } } func TestRunCancellationIsNotAnError(t *testing.T) { var calls atomic.Int32 s := New(5*time.Millisecond, func(ctx context.Context) error { calls.Add(1) time.Sleep(50 * time.Millisecond) // outlive cancellation return ctx.Err() }) ctx, cancel := context.WithCancel(context.Background()) done := make(chan error, 1) go func() { done <- s.Run(ctx) }() time.Sleep(12 * time.Millisecond) cancel() if err := <-done; err != nil { t.Fatalf("Run returned %v on cancellation, want nil", err) } }