github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/pkg/upstream/manager_test.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 upstream
    15  
    16  import (
    17  	"context"
    18  	"sync"
    19  	"testing"
    20  
    21  	"github.com/benbjohnson/clock"
    22  	"github.com/pingcap/errors"
    23  	"github.com/pingcap/tiflow/cdc/model"
    24  	"github.com/pingcap/tiflow/pkg/orchestrator"
    25  	"github.com/pingcap/tiflow/pkg/security"
    26  	"github.com/pingcap/tiflow/pkg/txnutil/gc"
    27  	"github.com/stretchr/testify/require"
    28  	"go.uber.org/atomic"
    29  )
    30  
    31  func TestUpstream(t *testing.T) {
    32  	pdClient := &gc.MockPDClient{}
    33  	manager := NewManager4Test(pdClient)
    34  
    35  	up1, ok1 := manager.Get(testUpstreamID)
    36  	require.True(t, ok1)
    37  	require.NotNil(t, up1)
    38  
    39  	// test Add
    40  	manager.add(testUpstreamID, []string{}, nil)
    41  
    42  	// test Get
    43  	testID := uint64(21)
    44  	up, ok := manager.Get(testID)
    45  	require.Nil(t, up)
    46  	require.False(t, ok)
    47  	up2 := NewUpstream4Test(pdClient)
    48  	up2.ID = testID
    49  	mockClock := clock.NewMock()
    50  	up2.clock = mockClock
    51  
    52  	manager.ups.Store(testID, up2)
    53  	up, ok = manager.Get(testID)
    54  	require.True(t, ok)
    55  	require.NotNil(t, up)
    56  
    57  	// test Tick
    58  	globalState := &orchestrator.GlobalReactorState{
    59  		Changefeeds: make(map[model.ChangeFeedID]*orchestrator.ChangefeedReactorState),
    60  	}
    61  	// add one changefeed state whose info is nil to make sure it won't be checked
    62  	globalState.Changefeeds[model.DefaultChangeFeedID("1")] = &orchestrator.ChangefeedReactorState{
    63  		Info: nil,
    64  	}
    65  	_ = manager.Tick(context.Background(), globalState)
    66  	mockClock.Add(maxIdleDuration * 2)
    67  	manager.lastTickTime = atomic.Time{}
    68  	_ = manager.Tick(context.Background(), globalState)
    69  	// wait until up2 is closed
    70  	for !up2.IsClosed() {
    71  	}
    72  	manager.lastTickTime = atomic.Time{}
    73  	_ = manager.Tick(context.Background(), globalState)
    74  	_ = manager.Tick(context.Background(), globalState)
    75  	up, ok = manager.Get(testID)
    76  	require.False(t, ok)
    77  	require.Nil(t, up)
    78  	up, ok = manager.Get(testUpstreamID)
    79  	require.True(t, ok)
    80  	require.NotNil(t, up)
    81  }
    82  
    83  func TestRemoveErrorUpstream(t *testing.T) {
    84  	pdClient := &gc.MockPDClient{}
    85  	manager := NewManager4Test(pdClient)
    86  	up1 := NewUpstream4Test(pdClient)
    87  	manager.ups.Store(uint64(4), up1)
    88  	up2 := NewUpstream4Test(pdClient)
    89  	up2.err.Store(errors.New("test"))
    90  	manager.ups.Store(testUpstreamID, up2)
    91  	up, ok := manager.Get(testUpstreamID)
    92  	require.True(t, ok)
    93  	require.NotNil(t, up)
    94  	_ = manager.Tick(context.Background(), &orchestrator.GlobalReactorState{
    95  		Changefeeds: map[model.ChangeFeedID]*orchestrator.ChangefeedReactorState{
    96  			model.DefaultChangeFeedID("1"): {
    97  				Info: &model.ChangeFeedInfo{UpstreamID: testUpstreamID},
    98  			},
    99  			model.DefaultChangeFeedID("4"): {
   100  				Info: &model.ChangeFeedInfo{UpstreamID: 4},
   101  			},
   102  		},
   103  	})
   104  	up, ok = manager.Get(testUpstreamID)
   105  	require.False(t, ok)
   106  	require.Nil(t, up)
   107  }
   108  
   109  func TestAddDefaultUpstream(t *testing.T) {
   110  	m := NewManager(context.Background(), CaptureTopologyCfg{GCServiceID: "id"})
   111  	m.initUpstreamFunc = func(context.Context, *Upstream, CaptureTopologyCfg) error {
   112  		return errors.New("test")
   113  	}
   114  
   115  	pdClient := &gc.MockPDClient{}
   116  
   117  	_, err := m.AddDefaultUpstream([]string{}, &security.Credential{}, pdClient, nil)
   118  	require.NotNil(t, err)
   119  	up, err := m.GetDefaultUpstream()
   120  	require.Nil(t, up)
   121  	require.NotNil(t, err)
   122  	m.initUpstreamFunc = func(_ context.Context, up *Upstream, _ CaptureTopologyCfg) error {
   123  		up.ID = uint64(2)
   124  		return nil
   125  	}
   126  	_, err = m.AddDefaultUpstream([]string{}, &security.Credential{}, pdClient, nil)
   127  	require.Nil(t, err)
   128  	up, err = m.GetDefaultUpstream()
   129  	require.NotNil(t, up)
   130  	require.Nil(t, err)
   131  	up, ok := m.Get(uint64(2))
   132  	require.NotNil(t, up)
   133  	require.True(t, ok)
   134  }
   135  
   136  func TestAddUpstream(t *testing.T) {
   137  	m := NewManager(context.Background(), CaptureTopologyCfg{GCServiceID: "id"})
   138  	m.initUpstreamFunc = func(context.Context, *Upstream, CaptureTopologyCfg) error {
   139  		return errors.New("test")
   140  	}
   141  	up := m.AddUpstream(&model.UpstreamInfo{ID: uint64(3)})
   142  	require.NotNil(t, up)
   143  	up1, ok := m.Get(uint64(3))
   144  	require.NotNil(t, up1)
   145  	require.True(t, ok)
   146  	require.False(t, up1.IsNormal())
   147  	for up.Error() == nil {
   148  	}
   149  	require.NotNil(t, up.Error())
   150  }
   151  
   152  func TestCloseManager(t *testing.T) {
   153  	ctx := context.TODO()
   154  	m := &Manager{
   155  		ups: &sync.Map{},
   156  	}
   157  	ctx, cancel := context.WithCancel(ctx)
   158  	m.ctx = ctx
   159  	m.cancel = cancel
   160  	up := &Upstream{
   161  		wg: new(sync.WaitGroup),
   162  	}
   163  	_, cancel = context.WithCancel(ctx)
   164  	up.cancel = cancel
   165  	m.ups.Store(uint64(1), up)
   166  	m.Close()
   167  	require.Equal(t, closed, up.status)
   168  	_, ok := m.ups.Load(uint64(1))
   169  	require.False(t, ok)
   170  }
   171  
   172  func TestRemoveThenAddAgain(t *testing.T) {
   173  	m := NewManager(context.Background(), CaptureTopologyCfg{GCServiceID: "id"})
   174  	m.initUpstreamFunc = func(context.Context, *Upstream, CaptureTopologyCfg) error {
   175  		return nil
   176  	}
   177  	up := m.AddUpstream(&model.UpstreamInfo{ID: uint64(3)})
   178  	require.NotNil(t, up)
   179  	// test Tick
   180  	_ = m.Tick(context.Background(), &orchestrator.GlobalReactorState{})
   181  	require.False(t, up.idleTime.IsZero())
   182  	_ = m.AddUpstream(&model.UpstreamInfo{ID: uint64(3)})
   183  	require.True(t, up.idleTime.IsZero())
   184  }