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  }