// Copyright 2023 schukai GmbH // SPDX-License-Identifier: AGPL-3.0 package jobqueue import ( "encoding/json" "github.com/robfig/cron/v3" "github.com/stretchr/testify/assert" "io/ioutil" "os" "testing" "time" ) func TestCreateJobAndSchedulerFromInput(t *testing.T) { tests := []struct { name string input JobPersistence wantJob GenericJob wantSched Scheduler wantErr bool }{ { name: "Shell Runnable and Interval Scheduler", input: JobPersistence{ ID: "1", Priority: 1, Timeout: 10 * time.Second, MaxRetries: 3, RetryDelay: 2 * time.Second, Runnable: RunnableImport{ Type: "Shell", Data: map[string]any{"ScriptPath": "script.sh"}, }, Scheduler: SchedulerPersistence{ Type: "Interval", Interval: 1 * time.Minute, }, }, wantJob: GenericJob(&Job[ShellResult]{ /* Initialization */ }), wantSched: &IntervalScheduler{Interval: 1 * time.Minute}, wantErr: false, }, { name: "Shell Runnable and Cron Scheduler", input: JobPersistence{ ID: "1", Priority: 1, Runnable: RunnableImport{ Type: "Shell", Data: map[string]any{"ScriptPath": "script.sh"}, }, Scheduler: SchedulerPersistence{ Type: "Cron", Spec: "* * * * * *", }, }, wantJob: GenericJob(&Job[ShellResult]{ /* Initialization */ }), wantSched: &CronScheduler{ /* Initialization */ }, wantErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { gotJob, gotSchedule, err := CreateJobAndSchedulerFromPersistence(tt.input, nil) if gotSchedule != nil { if gotSchedule.GetType() == "Cron" { cronInst := cron.New(cron.WithSeconds()) gotSchedule.(*CronScheduler).cron = cronInst cronInst.Start() defer cronInst.Stop() } } if (err != nil) != tt.wantErr { t.Errorf("CreateJobAndSchedulerFromPersistence() error = %v, wantErr %v", err, tt.wantErr) return } assert.Equal(t, JobID(tt.input.ID), gotJob.GetID(), "Job ID mismatch") assert.Equal(t, Priority(tt.input.Priority), gotJob.GetPriority(), "Job Priority mismatch") assert.Equal(t, tt.input.Scheduler.Type, gotSchedule.GetType(), "Scheduler Type mismatch") }) } } func TestReadJsonFile(t *testing.T) { testContent := `[{"id": "1", "priority": 1}]` tempFile, err := ioutil.TempFile("", "test.json") if err != nil { t.Fatal(err) } defer os.Remove(tempFile.Name()) if _, err := tempFile.Write([]byte(testContent)); err != nil { t.Fatal(err) } tempFile.Close() jobs, err := ReadJsonFile(tempFile.Name()) if err != nil { t.Fatal(err) } if len(jobs) != 1 || jobs[0].ID != "1" || jobs[0].Priority != 1 { t.Errorf("Expected job with ID '1' and priority 1, got %+v", jobs) } } func TestReadYAMLFile(t *testing.T) { testContent := `- id: "1" priority: 1 ` tempFile, err := ioutil.TempFile("", "test.yaml") if err != nil { t.Fatal(err) } defer os.Remove(tempFile.Name()) if _, err := tempFile.Write([]byte(testContent)); err != nil { t.Fatal(err) } tempFile.Close() jobs, err := ReadYAMLFile(tempFile.Name()) if err != nil { t.Fatal(err) } if len(jobs) != 1 || jobs[0].ID != "1" || jobs[0].Priority != 1 { t.Errorf("Expected job with ID '1' and priority 1, got %+v", jobs) } } func TestJobPersistenceUnmarshalJSON(t *testing.T) { testCases := []struct { name string jsonInput string expected *time.Time wantErr bool }{ { name: "RFC3339 Format", jsonInput: `{"pauseUntil":"2023-11-15T09:01:00Z"}`, expected: parseTimeForTesting(t, "2023-11-15T09:01:00Z"), wantErr: false, }, { name: "Date and Time", jsonInput: `{"pauseUntil":"2023-11-15T09:01"}`, expected: parseTimeForTesting(t, "2023-11-15T09:01"), wantErr: false, }, { name: "Only Date", jsonInput: `{"pauseUntil":"2023-11-15"}`, expected: parseTimeForTesting(t, "2023-11-15"), wantErr: false, }, { name: "Invalid Format", jsonInput: `{"pauseUntil":"15. November 2023"}`, expected: nil, wantErr: true, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { var jp JobPersistence err := json.Unmarshal([]byte(tc.jsonInput), &jp) if tc.wantErr { assert.Error(t, err) } else { assert.NoError(t, err) assert.Equal(t, tc.expected, jp.PauseUntil) } }) } }