github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/cdc/api/v2/api_helpers_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 v2 15 16 import ( 17 "context" 18 "testing" 19 "time" 20 21 "github.com/golang/mock/gomock" 22 mock_controller "github.com/pingcap/tiflow/cdc/controller/mock" 23 "github.com/pingcap/tiflow/cdc/entry" 24 "github.com/pingcap/tiflow/cdc/model" 25 "github.com/pingcap/tiflow/pkg/config" 26 cerror "github.com/pingcap/tiflow/pkg/errors" 27 "github.com/pingcap/tiflow/pkg/util" 28 "github.com/stretchr/testify/require" 29 ) 30 31 func TestVerifyCreateChangefeedConfig(t *testing.T) { 32 ctx := context.Background() 33 pdClient := &mockPDClient{} 34 helper := entry.NewSchemaTestHelper(t) 35 defer helper.Close() 36 helper.Tk().MustExec("use test;") 37 storage := helper.Storage() 38 ctrl := mock_controller.NewMockController(gomock.NewController(t)) 39 cfg := &ChangefeedConfig{} 40 h := &APIV2HelpersImpl{} 41 cfInfo, err := h.verifyCreateChangefeedConfig(ctx, cfg, pdClient, ctrl, "en", storage) 42 require.Nil(t, cfInfo) 43 require.NotNil(t, err) 44 cfg.SinkURI = "blackhole://" 45 ctrl.EXPECT().IsChangefeedExists(gomock.Any(), gomock.Any()).Return(false, nil) 46 // repliconfig is nil 47 require.Panics(t, func() { 48 _, _ = h.verifyCreateChangefeedConfig(ctx, cfg, pdClient, ctrl, "en", storage) 49 }) 50 cfg.ReplicaConfig = GetDefaultReplicaConfig() 51 cfg.ReplicaConfig.ForceReplicate = false 52 cfg.ReplicaConfig.IgnoreIneligibleTable = true 53 cfg.SinkURI = "blackhole://" 54 ctrl.EXPECT().IsChangefeedExists(gomock.Any(), gomock.Any()).Return(false, nil) 55 cfInfo, err = h.verifyCreateChangefeedConfig(ctx, cfg, pdClient, ctrl, "en", storage) 56 require.Nil(t, err) 57 require.NotNil(t, cfInfo) 58 require.NotEqual(t, "", cfInfo.ID) 59 require.Equal(t, model.DefaultNamespace, cfInfo.Namespace) 60 require.NotEqual(t, 0, cfInfo.Epoch) 61 62 // invalid changefeed id or namespace id 63 cfg.ID = "abdc/sss" 64 _, err = h.verifyCreateChangefeedConfig(ctx, cfg, pdClient, ctrl, "en", storage) 65 require.NotNil(t, err) 66 cfg.ID = "" 67 cfg.Namespace = "abdc/sss" 68 _, err = h.verifyCreateChangefeedConfig(ctx, cfg, pdClient, ctrl, "en", storage) 69 require.NotNil(t, err) 70 cfg.ID = "" 71 cfg.Namespace = "" 72 // changefeed already exists 73 ctrl.EXPECT().IsChangefeedExists(gomock.Any(), gomock.Any()).Return(true, nil) 74 _, err = h.verifyCreateChangefeedConfig(ctx, cfg, pdClient, ctrl, "en", storage) 75 require.NotNil(t, err) 76 ctrl.EXPECT().IsChangefeedExists(gomock.Any(), gomock.Any()).Return(false, cerror.ErrChangeFeedNotExists.GenWithStackByArgs("aaa")) 77 _, err = h.verifyCreateChangefeedConfig(ctx, cfg, pdClient, ctrl, "en", storage) 78 require.Nil(t, err) 79 require.Equal(t, uint64(123), cfInfo.UpstreamID) 80 cfg.TargetTs = 3 81 cfg.StartTs = 4 82 ctrl.EXPECT().IsChangefeedExists(gomock.Any(), gomock.Any()).Return(false, nil) 83 _, err = h.verifyCreateChangefeedConfig(ctx, cfg, pdClient, ctrl, "en", storage) 84 require.NotNil(t, err) 85 cfg.TargetTs = 6 86 cfg.SinkURI = "aaab://" 87 ctrl.EXPECT().IsChangefeedExists(gomock.Any(), gomock.Any()).Return(false, nil) 88 _, err = h.verifyCreateChangefeedConfig(ctx, cfg, pdClient, ctrl, "en", storage) 89 require.NotNil(t, err) 90 cfg.SinkURI = string([]byte{0x7f, ' '}) 91 ctrl.EXPECT().IsChangefeedExists(gomock.Any(), gomock.Any()).Return(false, nil) 92 _, err = h.verifyCreateChangefeedConfig(ctx, cfg, pdClient, ctrl, "en", storage) 93 require.NotNil(t, err) 94 95 cfg.StartTs = 0 96 // use blackhole to workaround 97 cfg.SinkURI = "blackhole://127.0.0.1:9092/test?protocol=avro" 98 cfg.ReplicaConfig.ForceReplicate = false 99 ctrl.EXPECT().IsChangefeedExists(gomock.Any(), gomock.Any()).Return(false, nil) 100 _, err = h.verifyCreateChangefeedConfig(ctx, cfg, pdClient, ctrl, "en", storage) 101 require.NoError(t, err) 102 103 cfg.ReplicaConfig.ForceReplicate = true 104 ctrl.EXPECT().IsChangefeedExists(gomock.Any(), gomock.Any()).Return(false, nil) 105 _, err = h.verifyCreateChangefeedConfig(ctx, cfg, pdClient, ctrl, "en", storage) 106 require.Error(t, cerror.ErrOldValueNotEnabled, err) 107 108 // invalid start-ts, in the future 109 cfg.StartTs = 1000000000000000000 110 ctrl.EXPECT().IsChangefeedExists(gomock.Any(), gomock.Any()).Return(false, nil) 111 _, err = h.verifyCreateChangefeedConfig(ctx, cfg, pdClient, ctrl, "en", storage) 112 require.Error(t, cerror.ErrAPIInvalidParam, err) 113 } 114 115 func TestVerifyUpdateChangefeedConfig(t *testing.T) { 116 ctx := context.Background() 117 cfg := &ChangefeedConfig{} 118 oldInfo := &model.ChangeFeedInfo{ 119 Config: config.GetDefaultReplicaConfig(), 120 } 121 oldUpInfo := &model.UpstreamInfo{} 122 helper := entry.NewSchemaTestHelper(t) 123 helper.Tk().MustExec("use test;") 124 storage := helper.Storage() 125 h := &APIV2HelpersImpl{} 126 newCfInfo, newUpInfo, err := h.verifyUpdateChangefeedConfig(ctx, cfg, oldInfo, oldUpInfo, storage, 0) 127 require.NotNil(t, err) 128 require.Nil(t, newCfInfo) 129 require.Nil(t, newUpInfo) 130 // namespace and id can not be updated 131 cfg.Namespace = "abc" 132 cfg.ID = "1234" 133 newCfInfo, newUpInfo, err = h.verifyUpdateChangefeedConfig(ctx, cfg, oldInfo, oldUpInfo, storage, 0) 134 require.NotNil(t, err) 135 require.Nil(t, newCfInfo) 136 require.Nil(t, newUpInfo) 137 cfg.StartTs = 2 138 cfg.TargetTs = 10 139 cfg.ReplicaConfig = ToAPIReplicaConfig(config.GetDefaultReplicaConfig()) 140 cfg.ReplicaConfig.SyncPointInterval = &JSONDuration{30 * time.Second} 141 cfg.PDAddrs = []string{"a", "b"} 142 cfg.CertPath = "p1" 143 cfg.CAPath = "p2" 144 cfg.KeyPath = "p3" 145 cfg.SinkURI = "blackhole://" 146 cfg.CertAllowedCN = []string{"c", "d"} 147 newCfInfo, newUpInfo, err = h.verifyUpdateChangefeedConfig(ctx, cfg, oldInfo, oldUpInfo, storage, 0) 148 require.Nil(t, err) 149 // startTs can not be updated 150 require.Equal(t, uint64(0), newCfInfo.StartTs) 151 require.Equal(t, uint64(10), newCfInfo.TargetTs) 152 require.Equal(t, 30*time.Second, util.GetOrZero(newCfInfo.Config.SyncPointInterval)) 153 require.Equal(t, cfg.ReplicaConfig.ToInternalReplicaConfig(), newCfInfo.Config) 154 require.Equal(t, "a,b", newUpInfo.PDEndpoints) 155 require.Equal(t, "p1", newUpInfo.CertPath) 156 require.Equal(t, "p2", newUpInfo.CAPath) 157 require.Equal(t, "p3", newUpInfo.KeyPath) 158 require.Equal(t, []string{"c", "d"}, newUpInfo.CertAllowedCN) 159 require.Equal(t, "blackhole://", newCfInfo.SinkURI) 160 oldInfo.StartTs = 10 161 cfg.TargetTs = 9 162 newCfInfo, newUpInfo, err = h.verifyUpdateChangefeedConfig(ctx, cfg, oldInfo, oldUpInfo, storage, 0) 163 require.NotNil(t, err) 164 }