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 }