diff --git a/errors.go b/errors.go index f5ebef4..7549135 100644 --- a/errors.go +++ b/errors.go @@ -20,6 +20,8 @@ var ( ErrMonthlyJobMinutesSeconds = fmt.Errorf("gocron: MonthlyJob: atTimes minutes and seconds must be between 0 and 59 inclusive") ErrNewJobTaskNil = fmt.Errorf("gocron: NewJob: Task must not be nil") ErrNewJobTaskNotFunc = fmt.Errorf("gocron: NewJob: Task.Function must be of kind reflect.Func") + ErrNewJobWrongNumberOfParameters = fmt.Errorf("gocron: NewJob: Number of provided parameters does not match expected") + ErrNewJobWrongTypeOfParameters = fmt.Errorf("gocron: NewJob: Type of provided parameters does not match expected") ErrStopExecutorTimedOut = fmt.Errorf("gocron: timed out waiting for executor to stop") ErrStopJobsTimedOut = fmt.Errorf("gocron: timed out waiting for jobs to finish") ErrStopSchedulerTimedOut = fmt.Errorf("gocron: timed out waiting for scheduler to stop") diff --git a/scheduler.go b/scheduler.go index 6101e58..644a70e 100644 --- a/scheduler.go +++ b/scheduler.go @@ -402,6 +402,25 @@ func (s *scheduler) addOrUpdateJob(id uuid.UUID, definition JobDefinition, taskW return nil, ErrNewJobTaskNotFunc } + expectedParameterLength := taskFunc.Type().NumIn() + if len(tsk.parameters) != expectedParameterLength { + return nil, ErrNewJobWrongNumberOfParameters + } + + for i := 0; i < expectedParameterLength; i++ { + t1 := reflect.TypeOf(tsk.parameters[i]).Kind() + if t1 == reflect.Interface || t1 == reflect.Pointer { + t1 = reflect.TypeOf(tsk.parameters[i]).Elem().Kind() + } + t2 := reflect.New(taskFunc.Type().In(i)).Elem().Kind() + if t2 == reflect.Interface || t2 == reflect.Pointer { + t2 = reflect.Indirect(reflect.ValueOf(taskFunc.Type().In(i))).Kind() + } + if t1 != t2 { + return nil, ErrNewJobWrongTypeOfParameters + } + } + j.name = runtime.FuncForPC(taskFunc.Pointer()).Name() j.function = tsk.function j.parameters = tsk.parameters diff --git a/scheduler_test.go b/scheduler_test.go index eab8ac4..c1051c1 100644 --- a/scheduler_test.go +++ b/scheduler_test.go @@ -748,6 +748,8 @@ func TestScheduler_NewJobTask(t *testing.T) { goleak.VerifyNone(t) testFuncPtr := func() {} + testFuncWithParams := func(one, two string) {} + testStruct := struct{}{} tests := []struct { name string @@ -774,6 +776,66 @@ func TestScheduler_NewJobTask(t *testing.T) { NewTask(&testFuncPtr), nil, }, + { + "parameter number does not match", + NewTask(testFuncWithParams, "one"), + ErrNewJobWrongNumberOfParameters, + }, + { + "parameter type does not match", + NewTask(testFuncWithParams, "one", 2), + ErrNewJobWrongTypeOfParameters, + }, + { + "parameter number does not match - ptr", + NewTask(&testFuncWithParams, "one"), + ErrNewJobWrongNumberOfParameters, + }, + { + "parameter type does not match - ptr", + NewTask(&testFuncWithParams, "one", 2), + ErrNewJobWrongTypeOfParameters, + }, + { + "all good struct", + NewTask(func(one struct{}) {}, struct{}{}), + nil, + }, + { + "all good interface", + NewTask(func(one interface{}) {}, struct{}{}), + nil, + }, + { + "all good any", + NewTask(func(one any) {}, struct{}{}), + nil, + }, + { + "all good slice", + NewTask(func(one []struct{}) {}, []struct{}{}), + nil, + }, + { + "all good chan", + NewTask(func(one chan struct{}) {}, make(chan struct{})), + nil, + }, + { + "all good pointer", + NewTask(func(one *struct{}) {}, &testStruct), + nil, + }, + { + "all good map", + NewTask(func(one map[string]struct{}) {}, make(map[string]struct{})), + nil, + }, + { + "all good", + NewTask(&testFuncWithParams, "one", "two"), + nil, + }, } for _, tt := range tests {