github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/syncer/handle_error_test.go (about) 1 // Copyright 2020 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 syncer 15 16 import ( 17 "context" 18 "fmt" 19 "testing" 20 21 "github.com/pingcap/tiflow/dm/pb" 22 "github.com/pingcap/tiflow/dm/pkg/conn" 23 "github.com/pingcap/tiflow/dm/syncer/binlogstream" 24 "github.com/pingcap/tiflow/dm/syncer/dbconn" 25 "github.com/stretchr/testify/require" 26 ) 27 28 func TestHandleError(t *testing.T) { 29 t.Parallel() 30 31 var ( 32 cfg = genDefaultSubTaskConfig4Test() 33 syncer = NewSyncer(cfg, nil, nil) 34 task = "test" 35 ctx = context.Background() 36 cases = []struct { 37 req *pb.HandleWorkerErrorRequest 38 errMsg string 39 }{ 40 { 41 req: &pb.HandleWorkerErrorRequest{Op: pb.ErrorOp_Replace, Task: task, BinlogPos: "", Sqls: []string{""}}, 42 errMsg: fmt.Sprintf("source '%s' has no error", syncer.cfg.SourceID), 43 }, 44 { 45 req: &pb.HandleWorkerErrorRequest{Op: pb.ErrorOp_Replace, Task: task, BinlogPos: "wrong_binlog_pos", Sqls: []string{""}}, 46 errMsg: ".*invalid --binlog-pos .* in handle-error operation.*", 47 }, 48 { 49 req: &pb.HandleWorkerErrorRequest{Op: pb.ErrorOp_Replace, Task: task, BinlogPos: "mysql-bin.000001:2345", Sqls: []string{"wrong_sql"}}, 50 errMsg: ".* sql wrong_sql: .*", 51 }, 52 { 53 req: &pb.HandleWorkerErrorRequest{Op: pb.ErrorOp_Replace, Task: task, BinlogPos: "mysql-bin.000001:2345", Sqls: []string{"alter table tb add column a int;"}}, 54 errMsg: ".*without schema name not valid.*", 55 }, 56 { 57 req: &pb.HandleWorkerErrorRequest{Op: pb.ErrorOp_Replace, Task: task, BinlogPos: "mysql-bin.000001:2345", Sqls: []string{"insert into db.tb values(1,2);"}}, 58 errMsg: ".*only support replace or inject with DDL currently.*", 59 }, 60 { 61 req: &pb.HandleWorkerErrorRequest{Op: pb.ErrorOp_Replace, Task: task, BinlogPos: "mysql-bin.000001:2345", Sqls: []string{"alter table db.tb add column a int;"}}, 62 errMsg: "", 63 }, 64 { 65 req: &pb.HandleWorkerErrorRequest{Op: pb.ErrorOp_Inject, Task: task, BinlogPos: "", Sqls: []string{""}}, 66 errMsg: fmt.Sprintf("source '%s' has no error", syncer.cfg.SourceID), 67 }, 68 { 69 req: &pb.HandleWorkerErrorRequest{Op: pb.ErrorOp_Inject, Task: task, BinlogPos: "wrong_binlog_pos", Sqls: []string{""}}, 70 errMsg: ".*invalid --binlog-pos .* in handle-error operation.*", 71 }, 72 { 73 req: &pb.HandleWorkerErrorRequest{Op: pb.ErrorOp_Inject, Task: task, BinlogPos: "mysql-bin.000001:2345", Sqls: []string{"wrong_sql"}}, 74 errMsg: ".* sql wrong_sql: .*", 75 }, 76 { 77 req: &pb.HandleWorkerErrorRequest{Op: pb.ErrorOp_Inject, Task: task, BinlogPos: "mysql-bin.000001:2345", Sqls: []string{"alter table db.tb add column a int;"}}, 78 errMsg: "", 79 }, 80 { 81 req: &pb.HandleWorkerErrorRequest{Op: pb.ErrorOp_Skip, Task: task, BinlogPos: "mysql-bin.000001:2345", Sqls: []string{}}, 82 errMsg: "", 83 }, 84 { 85 req: &pb.HandleWorkerErrorRequest{Op: pb.ErrorOp_List, Task: task, BinlogPos: "mysql-bin.000001:2344", Sqls: []string{}}, 86 errMsg: "", 87 }, 88 } 89 ) 90 mockDB, err := conn.MockDefaultDBProvider() 91 require.NoError(t, err) 92 upstreamDB, err := conn.GetUpstreamDB(&cfg.From) // used to get parser 93 require.NoError(t, err) 94 syncer.fromDB = &dbconn.UpStreamConn{BaseDB: upstreamDB} 95 syncer.streamerController = binlogstream.NewStreamerController4Test(nil, nil) 96 97 for _, cs := range cases { 98 commandsJSON, err := syncer.HandleError(ctx, cs.req) 99 if cs.req.Op == pb.ErrorOp_List { 100 require.Equal(t, "[{\"op\":1,\"task\":\"test\",\"binlogPos\":\"(mysql-bin.000001, 2345)\"}]", commandsJSON) 101 } 102 if len(cs.errMsg) == 0 { 103 require.NoError(t, err) 104 } else { 105 require.Error(t, err) 106 require.Regexp(t, cs.errMsg, err.Error()) 107 } 108 } 109 require.NoError(t, mockDB.ExpectationsWereMet()) 110 }