github.com/blend/go-sdk@v1.20220411.3/cron/main_test.go (about) 1 /* 2 3 Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file. 5 6 */ 7 8 package cron 9 10 import ( 11 "context" 12 "os" 13 "sync" 14 "testing" 15 "time" 16 ) 17 18 // TestMain is the testing entrypoint. 19 func TestMain(m *testing.M) { 20 os.Exit(m.Run()) 21 } 22 23 func noop(_ context.Context) error { return nil } 24 25 const ( 26 runAtJobName = "runAt" 27 ) 28 29 type runAtJob struct { 30 RunAt time.Time 31 RunDelegate func(ctx context.Context) error 32 } 33 34 var ( 35 _ Schedule = (*runAt)(nil) 36 ) 37 38 type runAt time.Time 39 40 func (ra runAt) Next(after time.Time) time.Time { 41 if after.Before(time.Time(ra)) { 42 return time.Time(ra) 43 } 44 return time.Time{} 45 } 46 47 func (raj *runAtJob) Name() string { 48 return "runAt" 49 } 50 51 func (raj *runAtJob) Schedule() Schedule { 52 return runAt(raj.RunAt) 53 } 54 55 func (raj *runAtJob) Execute(ctx context.Context) error { 56 return raj.RunDelegate(ctx) 57 } 58 59 var ( 60 _ Job = (*testJobWithTimeout)(nil) 61 _ ConfigProvider = (*testJobWithTimeout)(nil) 62 _ LifecycleProvider = (*testJobWithTimeout)(nil) 63 ) 64 65 type testJobWithTimeout struct { 66 RunAt time.Time 67 TimeoutDuration time.Duration 68 RunDelegate func(ctx context.Context) error 69 CancellationDelegate func() 70 } 71 72 func (tj *testJobWithTimeout) Name() string { 73 return "testJobWithTimeout" 74 } 75 76 func (tj *testJobWithTimeout) Config() JobConfig { 77 return JobConfig{ 78 Timeout: tj.TimeoutDuration, 79 } 80 } 81 82 func (tj *testJobWithTimeout) Schedule() Schedule { 83 return Immediately() 84 } 85 86 func (tj *testJobWithTimeout) Execute(ctx context.Context) error { 87 return tj.RunDelegate(ctx) 88 } 89 90 func (tj *testJobWithTimeout) Lifecycle() JobLifecycle { 91 return JobLifecycle{ 92 OnCancellation: tj.OnCancellation, 93 } 94 } 95 96 func (tj *testJobWithTimeout) OnCancellation(ctx context.Context) { 97 tj.CancellationDelegate() 98 } 99 100 var ( 101 _ Job = (*testWithDisabled)(nil) 102 _ ConfigProvider = (*testWithDisabled)(nil) 103 ) 104 105 type testWithDisabled struct { 106 disabled bool 107 action func(context.Context) error 108 } 109 110 func (twe testWithDisabled) Name() string { 111 return "testWithEnabled" 112 } 113 114 func (twe testWithDisabled) Schedule() Schedule { 115 return nil 116 } 117 118 func (twe testWithDisabled) Config() JobConfig { 119 return JobConfig{ 120 Disabled: &twe.disabled, 121 } 122 } 123 124 func (twe testWithDisabled) Execute(ctx context.Context) error { 125 if twe.action != nil { 126 return twe.action(ctx) 127 } 128 return nil 129 } 130 131 type mockTracer struct { 132 OnStart func(context.Context, string) 133 OnFinish func(context.Context, error) 134 } 135 136 func (mt mockTracer) Start(ctx context.Context, jobName string) (context.Context, TraceFinisher) { 137 if mt.OnStart != nil { 138 mt.OnStart(ctx, jobName) 139 } 140 return ctx, &mockTraceFinisher{Parent: &mt} 141 } 142 143 type mockTraceFinisher struct { 144 Parent *mockTracer 145 } 146 147 func (mtf mockTraceFinisher) Finish(ctx context.Context, err error) { 148 if mtf.Parent != nil && mtf.Parent.OnFinish != nil { 149 mtf.Parent.OnFinish(ctx, err) 150 } 151 } 152 153 var ( 154 _ Job = (*lifecycleTest)(nil) 155 _ LifecycleProvider = (*lifecycleTest)(nil) 156 ) 157 158 func newLifecycleTest(action func(context.Context) error) *lifecycleTest { 159 return &lifecycleTest{ 160 CompleteSignal: make(chan struct{}), 161 SuccessSignal: make(chan struct{}), 162 BrokenSignal: make(chan struct{}), 163 FixedSignal: make(chan struct{}), 164 Action: action, 165 } 166 } 167 168 type lifecycleTest struct { 169 sync.Mutex 170 Starts int 171 Completes int 172 Successes int 173 Failures int 174 CompleteSignal chan struct{} 175 SuccessSignal chan struct{} 176 BrokenSignal chan struct{} 177 FixedSignal chan struct{} 178 Action func(context.Context) error 179 } 180 181 func (job *lifecycleTest) Name() string { return "lifecycle-test" } 182 func (job *lifecycleTest) Execute(ctx context.Context) error { 183 return job.Action(ctx) 184 } 185 func (job *lifecycleTest) Lifecycle() JobLifecycle { 186 return JobLifecycle{ 187 OnBegin: job.OnBegin, 188 OnComplete: job.OnComplete, 189 OnSuccess: job.OnSuccess, 190 OnError: job.OnError, 191 OnBroken: job.OnBroken, 192 OnFixed: job.OnFixed, 193 } 194 } 195 func (job *lifecycleTest) OnBegin(ctx context.Context) { 196 job.Starts++ 197 } 198 func (job *lifecycleTest) OnError(ctx context.Context) { 199 job.Failures++ 200 } 201 func (job *lifecycleTest) OnComplete(ctx context.Context) { 202 job.Lock() 203 defer job.Unlock() 204 close(job.CompleteSignal) 205 job.CompleteSignal = make(chan struct{}) 206 job.Completes++ 207 } 208 func (job *lifecycleTest) OnSuccess(ctx context.Context) { 209 job.Lock() 210 defer job.Unlock() 211 close(job.SuccessSignal) 212 job.SuccessSignal = make(chan struct{}) 213 job.Successes++ 214 } 215 func (job *lifecycleTest) OnBroken(ctx context.Context) { 216 job.Lock() 217 defer job.Unlock() 218 close(job.BrokenSignal) 219 job.BrokenSignal = make(chan struct{}) 220 } 221 func (job *lifecycleTest) OnFixed(ctx context.Context) { 222 job.Lock() 223 defer job.Unlock() 224 close(job.FixedSignal) 225 job.BrokenSignal = make(chan struct{}) 226 } 227 228 type loadJobTestMinimum struct{} 229 230 func (job loadJobTestMinimum) Name() string { return "load-job-test-minimum" } 231 func (job loadJobTestMinimum) Execute(_ context.Context) error { return nil } 232 233 var ( 234 _ Job = (*scheduleProvider)(nil) 235 _ ScheduleProvider = (*scheduleProvider)(nil) 236 ) 237 238 type scheduleProvider struct { 239 ScheduleProvider func() Schedule 240 Action func(context.Context) error 241 } 242 243 func (job scheduleProvider) Name() string { return "schedule-provider" } 244 func (job scheduleProvider) Schedule() Schedule { return job.ScheduleProvider() } 245 func (job scheduleProvider) Execute(ctx context.Context) error { return job.Action(ctx) }