github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/jobs/schedulers_test.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 package jobs 4 5 import ( 6 "sync" 7 "testing" 8 "time" 9 10 "github.com/stretchr/testify/assert" 11 12 "github.com/masterhung0112/hk_server/v5/einterfaces/mocks" 13 "github.com/masterhung0112/hk_server/v5/model" 14 "github.com/masterhung0112/hk_server/v5/plugin/plugintest/mock" 15 "github.com/masterhung0112/hk_server/v5/store/storetest/mockstore" 16 "github.com/masterhung0112/hk_server/v5/utils/testutils" 17 ) 18 19 type MockScheduler struct { 20 mock.Mock 21 } 22 23 func (scheduler *MockScheduler) Enabled(cfg *model.Config) bool { 24 return true 25 } 26 27 func (scheduler *MockScheduler) Name() string { 28 return "MockScheduler" 29 } 30 31 func (scheduler *MockScheduler) JobType() string { 32 return model.JOB_TYPE_DATA_RETENTION 33 } 34 35 func (scheduler *MockScheduler) NextScheduleTime(cfg *model.Config, now time.Time, pendingJobs bool, lastSuccessfulJob *model.Job) *time.Time { 36 nextTime := time.Now().Add(60 * time.Second) 37 return &nextTime 38 } 39 40 func (scheduler *MockScheduler) ScheduleJob(cfg *model.Config, pendingJobs bool, lastSuccessfulJob *model.Job) (*model.Job, *model.AppError) { 41 return nil, nil 42 } 43 44 func TestScheduler(t *testing.T) { 45 mockStore := &mockstore.Store{} 46 defer mockStore.AssertExpectations(t) 47 48 job := &model.Job{ 49 Id: model.NewId(), 50 CreateAt: model.GetMillis(), 51 Status: model.JOB_STATUS_PENDING, 52 Type: model.JOB_TYPE_MESSAGE_EXPORT, 53 } 54 // mock job store doesn't return a previously successful job, forcing fallback to config 55 mockStore.JobStore.On("GetNewestJobByStatusesAndType", mock.AnythingOfType("[]string"), mock.AnythingOfType("string")).Return(job, nil) 56 mockStore.JobStore.On("GetCountByStatusAndType", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(int64(1), nil) 57 58 jobServer := &JobServer{ 59 Store: mockStore, 60 ConfigService: &testutils.StaticConfigService{ 61 Cfg: &model.Config{ 62 // mock config 63 DataRetentionSettings: *&model.DataRetentionSettings{ 64 EnableMessageDeletion: model.NewBool(true), 65 }, 66 MessageExportSettings: *&model.MessageExportSettings{ 67 EnableExport: model.NewBool(true), 68 }, 69 }, 70 }, 71 } 72 73 jobInterface := new(mocks.DataRetentionJobInterface) 74 jobInterface.On("MakeScheduler").Return(new(MockScheduler)) 75 jobServer.DataRetentionJob = jobInterface 76 77 exportInterface := new(mocks.MessageExportJobInterface) 78 exportInterface.On("MakeScheduler").Return(new(MockScheduler)) 79 jobServer.MessageExportJob = exportInterface 80 81 t.Run("Base", func(t *testing.T) { 82 jobServer.InitSchedulers() 83 jobServer.StartSchedulers() 84 time.Sleep(time.Second) 85 86 jobServer.StopSchedulers() 87 // They should be all on here 88 for _, element := range jobServer.schedulers.nextRunTimes { 89 assert.NotNil(t, element) 90 } 91 }) 92 93 t.Run("ClusterLeaderChanged", func(t *testing.T) { 94 jobServer.InitSchedulers() 95 jobServer.StartSchedulers() 96 time.Sleep(time.Second) 97 jobServer.HandleClusterLeaderChange(false) 98 jobServer.StopSchedulers() 99 // They should be turned off 100 for _, element := range jobServer.schedulers.nextRunTimes { 101 assert.Nil(t, element) 102 } 103 }) 104 105 t.Run("ClusterLeaderChangedBeforeStart", func(t *testing.T) { 106 jobServer.InitSchedulers() 107 jobServer.HandleClusterLeaderChange(false) 108 jobServer.StartSchedulers() 109 time.Sleep(time.Second) 110 jobServer.StopSchedulers() 111 for _, element := range jobServer.schedulers.nextRunTimes { 112 assert.Nil(t, element) 113 } 114 }) 115 116 t.Run("DoubleClusterLeaderChangedBeforeStart", func(t *testing.T) { 117 jobServer.InitSchedulers() 118 jobServer.HandleClusterLeaderChange(false) 119 jobServer.HandleClusterLeaderChange(true) 120 jobServer.StartSchedulers() 121 time.Sleep(time.Second) 122 jobServer.StopSchedulers() 123 for _, element := range jobServer.schedulers.nextRunTimes { 124 assert.NotNil(t, element) 125 } 126 }) 127 t.Run("ConfigChanged", func(t *testing.T) { 128 jobServer.InitSchedulers() 129 jobServer.StartSchedulers() 130 time.Sleep(time.Second) 131 jobServer.HandleClusterLeaderChange(false) 132 // After running a config change, they should stay off 133 jobServer.schedulers.handleConfigChange(nil, nil) 134 jobServer.StopSchedulers() 135 for _, element := range jobServer.schedulers.nextRunTimes { 136 assert.Nil(t, element) 137 } 138 }) 139 140 t.Run("ConfigChangedDeadlock", func(t *testing.T) { 141 jobServer.InitSchedulers() 142 jobServer.StartSchedulers() 143 time.Sleep(time.Second) 144 145 var wg sync.WaitGroup 146 wg.Add(2) 147 go func() { 148 defer wg.Done() 149 jobServer.StopSchedulers() 150 }() 151 go func() { 152 defer wg.Done() 153 jobServer.schedulers.handleConfigChange(nil, nil) 154 }() 155 156 wg.Wait() 157 }) 158 }