first commit
Some checks failed
Backend Tests / Static Checks (push) Has been cancelled
Backend Tests / Tests (other) (push) Has been cancelled
Backend Tests / Tests (plugin) (push) Has been cancelled
Backend Tests / Tests (server) (push) Has been cancelled
Backend Tests / Tests (store) (push) Has been cancelled
Build Canary Image / build-frontend (push) Has been cancelled
Build Canary Image / build-push (linux/amd64) (push) Has been cancelled
Build Canary Image / build-push (linux/arm64) (push) Has been cancelled
Build Canary Image / merge (push) Has been cancelled
Frontend Tests / Lint (push) Has been cancelled
Frontend Tests / Build (push) Has been cancelled
Proto Linter / Lint Protos (push) Has been cancelled
Some checks failed
Backend Tests / Static Checks (push) Has been cancelled
Backend Tests / Tests (other) (push) Has been cancelled
Backend Tests / Tests (plugin) (push) Has been cancelled
Backend Tests / Tests (server) (push) Has been cancelled
Backend Tests / Tests (store) (push) Has been cancelled
Build Canary Image / build-frontend (push) Has been cancelled
Build Canary Image / build-push (linux/amd64) (push) Has been cancelled
Build Canary Image / build-push (linux/arm64) (push) Has been cancelled
Build Canary Image / merge (push) Has been cancelled
Frontend Tests / Lint (push) Has been cancelled
Frontend Tests / Build (push) Has been cancelled
Proto Linter / Lint Protos (push) Has been cancelled
This commit is contained in:
165
plugin/scheduler/scheduler_test.go
Normal file
165
plugin/scheduler/scheduler_test.go
Normal file
@@ -0,0 +1,165 @@
|
||||
package scheduler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSchedulerCreation(t *testing.T) {
|
||||
s := New()
|
||||
if s == nil {
|
||||
t.Fatal("New() returned nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSchedulerWithTimezone(t *testing.T) {
|
||||
s := New(WithTimezone("America/New_York"))
|
||||
if s == nil {
|
||||
t.Fatal("New() with timezone returned nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJobRegistration(t *testing.T) {
|
||||
s := New()
|
||||
|
||||
job := &Job{
|
||||
Name: "test-registration",
|
||||
Schedule: "0 * * * *",
|
||||
Handler: func(_ context.Context) error { return nil },
|
||||
}
|
||||
|
||||
if err := s.Register(job); err != nil {
|
||||
t.Fatalf("failed to register valid job: %v", err)
|
||||
}
|
||||
|
||||
// Registering duplicate name should fail
|
||||
if err := s.Register(job); err == nil {
|
||||
t.Error("expected error when registering duplicate job name")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSchedulerStartStop(t *testing.T) {
|
||||
s := New()
|
||||
|
||||
var runCount atomic.Int32
|
||||
job := &Job{
|
||||
Name: "test-start-stop",
|
||||
Schedule: "* * * * * *", // Every second (6-field format)
|
||||
Handler: func(_ context.Context) error {
|
||||
runCount.Add(1)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
if err := s.Register(job); err != nil {
|
||||
t.Fatalf("failed to register job: %v", err)
|
||||
}
|
||||
|
||||
// Start scheduler
|
||||
if err := s.Start(); err != nil {
|
||||
t.Fatalf("failed to start scheduler: %v", err)
|
||||
}
|
||||
|
||||
// Let it run for 2.5 seconds
|
||||
time.Sleep(2500 * time.Millisecond)
|
||||
|
||||
// Stop scheduler
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := s.Stop(ctx); err != nil {
|
||||
t.Fatalf("failed to stop scheduler: %v", err)
|
||||
}
|
||||
|
||||
count := runCount.Load()
|
||||
// Should have run at least twice (at 0s and 1s, maybe 2s)
|
||||
if count < 2 {
|
||||
t.Errorf("expected job to run at least 2 times, ran %d times", count)
|
||||
}
|
||||
|
||||
// Verify it stopped (count shouldn't increase)
|
||||
finalCount := count
|
||||
time.Sleep(1500 * time.Millisecond)
|
||||
if runCount.Load() != finalCount {
|
||||
t.Error("scheduler did not stop - job continued running")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSchedulerWithMiddleware(t *testing.T) {
|
||||
var executionLog []string
|
||||
var logMu sync.Mutex
|
||||
|
||||
logger := &testLogger{
|
||||
onInfo: func(msg string, _ ...interface{}) {
|
||||
logMu.Lock()
|
||||
executionLog = append(executionLog, fmt.Sprintf("INFO: %s", msg))
|
||||
logMu.Unlock()
|
||||
},
|
||||
onError: func(msg string, _ ...interface{}) {
|
||||
logMu.Lock()
|
||||
executionLog = append(executionLog, fmt.Sprintf("ERROR: %s", msg))
|
||||
logMu.Unlock()
|
||||
},
|
||||
}
|
||||
|
||||
s := New(WithMiddleware(
|
||||
Recovery(func(jobName string, r interface{}) {
|
||||
logMu.Lock()
|
||||
executionLog = append(executionLog, fmt.Sprintf("PANIC: %s - %v", jobName, r))
|
||||
logMu.Unlock()
|
||||
}),
|
||||
Logging(logger),
|
||||
))
|
||||
|
||||
job := &Job{
|
||||
Name: "test-middleware",
|
||||
Schedule: "* * * * * *", // Every second
|
||||
Handler: func(_ context.Context) error {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
if err := s.Register(job); err != nil {
|
||||
t.Fatalf("failed to register job: %v", err)
|
||||
}
|
||||
|
||||
if err := s.Start(); err != nil {
|
||||
t.Fatalf("failed to start: %v", err)
|
||||
}
|
||||
|
||||
time.Sleep(1500 * time.Millisecond)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := s.Stop(ctx); err != nil {
|
||||
t.Fatalf("failed to stop: %v", err)
|
||||
}
|
||||
|
||||
logMu.Lock()
|
||||
defer logMu.Unlock()
|
||||
|
||||
// Should have at least one start and one completion log
|
||||
hasStart := false
|
||||
hasCompletion := false
|
||||
for _, log := range executionLog {
|
||||
if strings.Contains(log, "Job started") {
|
||||
hasStart = true
|
||||
}
|
||||
if strings.Contains(log, "Job completed") {
|
||||
hasCompletion = true
|
||||
}
|
||||
}
|
||||
|
||||
if !hasStart {
|
||||
t.Error("expected job start log")
|
||||
}
|
||||
if !hasCompletion {
|
||||
t.Error("expected job completion log")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user