github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/engine/framework/mock_master_impl.go (about) 1 // Copyright 2022 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package framework 15 16 import ( 17 "context" 18 "encoding/json" 19 "sync" 20 "testing" 21 22 "github.com/pingcap/log" 23 "github.com/pingcap/tiflow/engine/framework/internal/master" 24 frameModel "github.com/pingcap/tiflow/engine/framework/model" 25 "github.com/pingcap/tiflow/engine/pkg/client" 26 dcontext "github.com/pingcap/tiflow/engine/pkg/context" 27 "github.com/pingcap/tiflow/engine/pkg/deps" 28 "github.com/pingcap/tiflow/engine/pkg/externalresource/broker" 29 metaMock "github.com/pingcap/tiflow/engine/pkg/meta/mock" 30 metaModel "github.com/pingcap/tiflow/engine/pkg/meta/model" 31 pkgOrm "github.com/pingcap/tiflow/engine/pkg/orm" 32 "github.com/pingcap/tiflow/engine/pkg/p2p" 33 "github.com/stretchr/testify/mock" 34 "go.uber.org/atomic" 35 "go.uber.org/dig" 36 "go.uber.org/zap" 37 ) 38 39 // MockMasterImpl implements a mock MasterImpl 40 type MockMasterImpl struct { 41 mu sync.Mutex 42 mock.Mock 43 44 *DefaultBaseMaster 45 masterID frameModel.MasterID 46 id frameModel.MasterID 47 tp frameModel.WorkerType 48 49 tickCount atomic.Int64 50 onlineWorkerCount atomic.Int64 51 52 dispatchedWorkers chan WorkerHandle 53 dispatchedResult chan error 54 updatedStatuses chan *frameModel.WorkerStatus 55 56 messageHandlerManager *p2p.MockMessageHandlerManager 57 messageSender p2p.MessageSender 58 frameMetaClient pkgOrm.Client 59 businessMetaKVClient *metaMock.MetaMock 60 executorGroup *client.MockExecutorGroup 61 serverMasterClient *client.MockServerMasterClient 62 } 63 64 // NewMockMasterImpl creates a new MockMasterImpl instance 65 func NewMockMasterImpl(t *testing.T, masterID, id frameModel.MasterID) *MockMasterImpl { 66 ret := &MockMasterImpl{ 67 masterID: masterID, 68 id: id, 69 tp: frameModel.FakeJobMaster, 70 dispatchedWorkers: make(chan WorkerHandle, 1), 71 dispatchedResult: make(chan error, 1), 72 updatedStatuses: make(chan *frameModel.WorkerStatus, 1024), 73 } 74 ret.DefaultBaseMaster = MockBaseMaster(t, id, ret) 75 ret.messageHandlerManager = ret.DefaultBaseMaster.messageHandlerManager.(*p2p.MockMessageHandlerManager) 76 ret.messageSender = ret.DefaultBaseMaster.messageSender 77 ret.frameMetaClient = ret.DefaultBaseMaster.frameMetaClient 78 ret.businessMetaKVClient = ret.DefaultBaseMaster.businessMetaKVClient.(*metaMock.MetaMock) 79 ret.executorGroup = ret.DefaultBaseMaster.executorGroup.(*client.MockExecutorGroup) 80 ret.serverMasterClient = ret.DefaultBaseMaster.serverMasterClient.(*client.MockServerMasterClient) 81 82 return ret 83 } 84 85 type masterParamListForTest struct { 86 dig.Out 87 88 MessageHandlerManager p2p.MessageHandlerManager 89 MessageSender p2p.MessageSender 90 FrameMetaClient pkgOrm.Client 91 BusinessClientConn metaModel.ClientConn 92 ExecutorGroup client.ExecutorGroup 93 ServerMasterClient client.ServerMasterClient 94 ResourceBroker broker.Broker 95 } 96 97 // GetFrameMetaClient returns the framework meta client. 98 func (m *MockMasterImpl) GetFrameMetaClient() pkgOrm.Client { 99 return m.frameMetaClient 100 } 101 102 // Reset resets the mock data. 103 func (m *MockMasterImpl) Reset() { 104 m.mu.Lock() 105 defer m.mu.Unlock() 106 107 m.Mock.ExpectedCalls = nil 108 m.Mock.Calls = nil 109 110 ctx := dcontext.Background() 111 dp := deps.NewDeps() 112 err := dp.Provide(func() masterParamListForTest { 113 return masterParamListForTest{ 114 MessageHandlerManager: m.messageHandlerManager, 115 MessageSender: m.messageSender, 116 FrameMetaClient: m.frameMetaClient, 117 BusinessClientConn: metaMock.NewMockClientConn(), 118 ExecutorGroup: m.executorGroup, 119 ServerMasterClient: m.serverMasterClient, 120 ResourceBroker: broker.NewBrokerForTesting("executor-1"), 121 } 122 }) 123 if err != nil { 124 panic(err) 125 } 126 127 ctx = ctx.WithDeps(dp) 128 m.DefaultBaseMaster = NewBaseMaster( 129 ctx, 130 m, 131 m.id, 132 m.tp, 133 ).(*DefaultBaseMaster) 134 } 135 136 // TickCount returns tick invoke time 137 func (m *MockMasterImpl) TickCount() int64 { 138 return m.tickCount.Load() 139 } 140 141 // InitImpl implements MasterImpl.InitImpl 142 func (m *MockMasterImpl) InitImpl(ctx context.Context) error { 143 m.mu.Lock() 144 defer m.mu.Unlock() 145 146 args := m.Called(ctx) 147 return args.Error(0) 148 } 149 150 // OnMasterRecovered implements MasterImpl.OnMasterRecovered 151 func (m *MockMasterImpl) OnMasterRecovered(ctx context.Context) error { 152 m.mu.Lock() 153 defer m.mu.Unlock() 154 155 args := m.Called(ctx) 156 return args.Error(0) 157 } 158 159 // OnWorkerStatusUpdated implements MasterImpl.OnWorkerStatusUpdated 160 func (m *MockMasterImpl) OnWorkerStatusUpdated(worker WorkerHandle, newStatus *frameModel.WorkerStatus) error { 161 m.mu.Lock() 162 defer m.mu.Unlock() 163 164 select { 165 case m.updatedStatuses <- newStatus: 166 default: 167 } 168 169 args := m.Called(worker, newStatus) 170 return args.Error(0) 171 } 172 173 // Tick implements MasterImpl.Tick 174 func (m *MockMasterImpl) Tick(ctx context.Context) error { 175 m.mu.Lock() 176 defer m.mu.Unlock() 177 178 m.tickCount.Add(1) 179 log.Info("tick") 180 181 args := m.Called(ctx) 182 return args.Error(0) 183 } 184 185 // OnWorkerDispatched implements MasterImpl.OnWorkerDispatched 186 func (m *MockMasterImpl) OnWorkerDispatched(worker WorkerHandle, result error) error { 187 m.mu.Lock() 188 defer m.mu.Unlock() 189 190 m.dispatchedWorkers <- worker 191 m.dispatchedResult <- result 192 193 args := m.Called(worker, result) 194 return args.Error(0) 195 } 196 197 // OnWorkerOnline implements MasterImpl.OnWorkerOnline 198 func (m *MockMasterImpl) OnWorkerOnline(worker WorkerHandle) error { 199 m.mu.Lock() 200 defer m.mu.Unlock() 201 202 log.Info("OnWorkerOnline", zap.Any("worker-id", worker.ID())) 203 m.onlineWorkerCount.Add(1) 204 205 args := m.Called(worker) 206 return args.Error(0) 207 } 208 209 // OnWorkerOffline implements MasterImpl.OnWorkerOffline 210 func (m *MockMasterImpl) OnWorkerOffline(worker WorkerHandle, reason error) error { 211 m.mu.Lock() 212 defer m.mu.Unlock() 213 214 m.onlineWorkerCount.Sub(1) 215 216 args := m.Called(worker, reason) 217 return args.Error(0) 218 } 219 220 // OnWorkerMessage implements MasterImpl.OnWorkerMessage 221 func (m *MockMasterImpl) OnWorkerMessage(worker WorkerHandle, topic p2p.Topic, message interface{}) error { 222 m.mu.Lock() 223 defer m.mu.Unlock() 224 225 args := m.Called(worker, topic, message) 226 return args.Error(0) 227 } 228 229 // CloseImpl implements MasterImpl.CloseImpl 230 func (m *MockMasterImpl) CloseImpl(ctx context.Context) { 231 m.mu.Lock() 232 defer m.mu.Unlock() 233 234 m.Called(ctx) 235 } 236 237 // StopImpl implements MasterImpl.StopImpl 238 func (m *MockMasterImpl) StopImpl(ctx context.Context) { 239 m.mu.Lock() 240 defer m.mu.Unlock() 241 242 m.Called(ctx) 243 } 244 245 // MasterClient returns internal server master client 246 func (m *MockMasterImpl) MasterClient() *client.MockServerMasterClient { 247 return m.serverMasterClient 248 } 249 250 type dummyStatus struct { 251 Val int 252 } 253 254 func (s *dummyStatus) Marshal() ([]byte, error) { 255 return json.Marshal(s) 256 } 257 258 func (s *dummyStatus) Unmarshal(data []byte) error { 259 return json.Unmarshal(data, s) 260 } 261 262 // MockWorkerHandler implements WorkerHandle, RunningHandle and TombstoneHandle interface 263 type MockWorkerHandler struct { 264 mock.Mock 265 266 WorkerID frameModel.WorkerID 267 } 268 269 // GetTombstone implements WorkerHandle.GetTombstone 270 func (m *MockWorkerHandler) GetTombstone() master.TombstoneHandle { 271 if m.IsTombStone() { 272 return m 273 } 274 return nil 275 } 276 277 // Unwrap implements WorkerHandle.Unwrap 278 func (m *MockWorkerHandler) Unwrap() master.RunningHandle { 279 if !m.IsTombStone() { 280 return m 281 } 282 return nil 283 } 284 285 // SendMessage implements RunningHandle.SendMessage 286 func (m *MockWorkerHandler) SendMessage(ctx context.Context, topic p2p.Topic, message interface{}, nonblocking bool) error { 287 args := m.Called(ctx, topic, message, nonblocking) 288 return args.Error(0) 289 } 290 291 // Status implements WorkerHandle.Status 292 func (m *MockWorkerHandler) Status() *frameModel.WorkerStatus { 293 args := m.Called() 294 return args.Get(0).(*frameModel.WorkerStatus) 295 } 296 297 // ID implements WorkerHandle.ID 298 func (m *MockWorkerHandler) ID() frameModel.WorkerID { 299 return m.WorkerID 300 } 301 302 // IsTombStone implements WorkerHandle.IsTombStone 303 func (m *MockWorkerHandler) IsTombStone() bool { 304 args := m.Called() 305 return args.Bool(0) 306 } 307 308 // CleanTombstone implements TombstoneHandle.CleanTombstone 309 func (m *MockWorkerHandler) CleanTombstone(ctx context.Context) error { 310 args := m.Called() 311 return args.Error(0) 312 }