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  }