mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-08 02:10:24 +08:00
149 lines
2.8 KiB
Go
149 lines
2.8 KiB
Go
|
|
package runner
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"github.com/stretchr/testify/require"
|
||
|
|
"mayfly-go/pkg/utils/timex"
|
||
|
|
"sync"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
var _ Job = &testJob{}
|
||
|
|
|
||
|
|
func newTestJob(key string, runTime time.Duration) *testJob {
|
||
|
|
return &testJob{
|
||
|
|
deadline: time.Now(),
|
||
|
|
Key: key,
|
||
|
|
run: func(ctx context.Context) {
|
||
|
|
timex.SleepWithContext(ctx, runTime)
|
||
|
|
},
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
type testJob struct {
|
||
|
|
run RunFunc
|
||
|
|
Key JobKey
|
||
|
|
status JobStatus
|
||
|
|
ran bool
|
||
|
|
deadline time.Time
|
||
|
|
}
|
||
|
|
|
||
|
|
func (t *testJob) Renew(job Job) {
|
||
|
|
}
|
||
|
|
|
||
|
|
func (t *testJob) GetDeadline() time.Time {
|
||
|
|
return t.deadline
|
||
|
|
}
|
||
|
|
|
||
|
|
func (t *testJob) Schedule() bool {
|
||
|
|
return !t.ran
|
||
|
|
}
|
||
|
|
|
||
|
|
func (t *testJob) Run(ctx context.Context) {
|
||
|
|
if t.run == nil {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
t.run(ctx)
|
||
|
|
t.ran = true
|
||
|
|
}
|
||
|
|
|
||
|
|
func (t *testJob) Runnable(_ NextFunc) bool {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
|
||
|
|
func (t *testJob) GetKey() JobKey {
|
||
|
|
return t.Key
|
||
|
|
}
|
||
|
|
|
||
|
|
func (t *testJob) GetStatus() JobStatus {
|
||
|
|
return t.status
|
||
|
|
}
|
||
|
|
|
||
|
|
func (t *testJob) SetStatus(status JobStatus) {
|
||
|
|
t.status = status
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestRunner_Close(t *testing.T) {
|
||
|
|
runner := NewRunner[*testJob](1)
|
||
|
|
signal := make(chan struct{}, 1)
|
||
|
|
waiting := sync.WaitGroup{}
|
||
|
|
waiting.Add(1)
|
||
|
|
go func() {
|
||
|
|
job := &testJob{
|
||
|
|
Key: "close",
|
||
|
|
run: func(ctx context.Context) {
|
||
|
|
waiting.Done()
|
||
|
|
timex.SleepWithContext(ctx, time.Hour)
|
||
|
|
signal <- struct{}{}
|
||
|
|
},
|
||
|
|
}
|
||
|
|
_ = runner.Add(context.Background(), job)
|
||
|
|
}()
|
||
|
|
waiting.Wait()
|
||
|
|
timer := time.NewTimer(time.Microsecond * 10)
|
||
|
|
runner.Close()
|
||
|
|
select {
|
||
|
|
case <-timer.C:
|
||
|
|
require.FailNow(t, "runner 未能及时退出")
|
||
|
|
case <-signal:
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestRunner_AddJob(t *testing.T) {
|
||
|
|
type testCase struct {
|
||
|
|
name string
|
||
|
|
job *testJob
|
||
|
|
want bool
|
||
|
|
}
|
||
|
|
testCases := []testCase{
|
||
|
|
{
|
||
|
|
name: "first job",
|
||
|
|
job: newTestJob("single", time.Hour),
|
||
|
|
want: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "second job",
|
||
|
|
job: newTestJob("dual", time.Hour),
|
||
|
|
want: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "non repetitive job",
|
||
|
|
job: newTestJob("single", time.Hour),
|
||
|
|
want: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "repetitive job",
|
||
|
|
job: newTestJob("dual", time.Hour),
|
||
|
|
want: true,
|
||
|
|
},
|
||
|
|
}
|
||
|
|
runner := NewRunner[*testJob](1)
|
||
|
|
defer runner.Close()
|
||
|
|
for _, tc := range testCases {
|
||
|
|
err := runner.Add(context.Background(), tc.job)
|
||
|
|
require.NoError(t, err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestJob_UpdateStatus(t *testing.T) {
|
||
|
|
const d = time.Millisecond * 20
|
||
|
|
runner := NewRunner[*testJob](1)
|
||
|
|
running := newTestJob("running", d*2)
|
||
|
|
waiting := newTestJob("waiting", d*2)
|
||
|
|
_ = runner.Add(context.Background(), running)
|
||
|
|
_ = runner.Add(context.Background(), waiting)
|
||
|
|
|
||
|
|
time.Sleep(d)
|
||
|
|
require.Equal(t, JobRunning, running.status)
|
||
|
|
require.Equal(t, JobWaiting, waiting.status)
|
||
|
|
|
||
|
|
time.Sleep(d * 2)
|
||
|
|
require.Equal(t, JobRemoved, running.status)
|
||
|
|
require.Equal(t, JobRunning, waiting.status)
|
||
|
|
|
||
|
|
time.Sleep(d * 2)
|
||
|
|
require.Equal(t, JobRemoved, running.status)
|
||
|
|
require.Equal(t, JobRemoved, waiting.status)
|
||
|
|
}
|