github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/pkg/binlog/reader/tcp_test.go (about)

     1  // Copyright 2019 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 reader
    15  
    16  import (
    17  	"context"
    18  	"strings"
    19  	"testing"
    20  
    21  	gmysql "github.com/go-mysql-org/go-mysql/mysql"
    22  	"github.com/go-mysql-org/go-mysql/replication"
    23  	_ "github.com/go-sql-driver/mysql"
    24  	"github.com/pingcap/failpoint"
    25  	"github.com/pingcap/tiflow/dm/pkg/binlog/common"
    26  	"github.com/pingcap/tiflow/dm/pkg/gtid"
    27  	"github.com/stretchr/testify/require"
    28  	"github.com/stretchr/testify/suite"
    29  )
    30  
    31  var (
    32  	flavor    = gmysql.MySQLFlavor
    33  	serverIDs = []uint32{3251, 3252}
    34  )
    35  
    36  func TestTCPReaderSuite(t *testing.T) {
    37  	suite.Run(t, new(testTCPReaderSuite))
    38  }
    39  
    40  type testTCPReaderSuite struct {
    41  	suite.Suite
    42  }
    43  
    44  func (t *testTCPReaderSuite) SetupSuite() {
    45  	require.Nil(t.T(), failpoint.Enable("github.com/pingcap/tiflow/dm/pkg/binlog/reader/MockTCPReaderStartSyncByPos", "return(true)"))
    46  	require.Nil(t.T(), failpoint.Enable("github.com/pingcap/tiflow/dm/pkg/binlog/reader/MockTCPReaderStartSyncByGTID", "return(true)"))
    47  	require.Nil(t.T(), failpoint.Enable("github.com/pingcap/tiflow/dm/pkg/binlog/reader/MockTCPReaderClose", "return(true)"))
    48  	require.Nil(t.T(), failpoint.Enable("github.com/pingcap/tiflow/dm/pkg/binlog/reader/MockTCPReaderGetEvent", "return(true)"))
    49  	require.Nil(t.T(), failpoint.Enable("github.com/pingcap/tiflow/dm/pkg/binlog/reader/MockTCPReaderStatus", "return(true)"))
    50  }
    51  
    52  func (t *testTCPReaderSuite) TearDownSuite() {
    53  	require.Nil(t.T(), failpoint.Disable("github.com/pingcap/tiflow/dm/pkg/binlog/reader/MockTCPReaderStartSyncByPos"))
    54  	require.Nil(t.T(), failpoint.Disable("github.com/pingcap/tiflow/dm/pkg/binlog/reader/MockTCPReaderStartSyncByGTID"))
    55  	require.Nil(t.T(), failpoint.Disable("github.com/pingcap/tiflow/dm/pkg/binlog/reader/MockTCPReaderClose"))
    56  	require.Nil(t.T(), failpoint.Disable("github.com/pingcap/tiflow/dm/pkg/binlog/reader/MockTCPReaderGetEvent"))
    57  	require.Nil(t.T(), failpoint.Disable("github.com/pingcap/tiflow/dm/pkg/binlog/reader/MockTCPReaderStatus"))
    58  }
    59  
    60  func (t *testTCPReaderSuite) TestSyncPos() {
    61  	var (
    62  		cfg = replication.BinlogSyncerConfig{ServerID: serverIDs[0], Flavor: flavor}
    63  		pos gmysql.Position // empty position
    64  	)
    65  
    66  	// the first reader
    67  	r := NewTCPReader(cfg)
    68  	require.NotNil(t.T(), r)
    69  
    70  	// not prepared
    71  	e, err := r.GetEvent(context.Background())
    72  	require.NotNil(t.T(), err)
    73  	require.Nil(t.T(), e)
    74  
    75  	// prepare
    76  	err = r.StartSyncByPos(pos)
    77  	require.Nil(t.T(), err)
    78  
    79  	// check status, stagePrepared
    80  	status := r.Status()
    81  	trStatus, ok := status.(*TCPReaderStatus)
    82  	require.True(t.T(), ok)
    83  	require.Equal(t.T(), common.StagePrepared.String(), trStatus.Stage)
    84  	require.Greater(t.T(), trStatus.ConnID, uint32(0))
    85  	trStatusStr := trStatus.String()
    86  	require.True(t.T(), strings.Contains(trStatusStr, common.StagePrepared.String()))
    87  	// re-prepare is invalid
    88  	err = r.StartSyncByPos(pos)
    89  	require.NotNil(t.T(), err)
    90  
    91  	// close the reader
    92  	err = r.Close()
    93  	require.Nil(t.T(), err)
    94  
    95  	// already closed
    96  	err = r.Close()
    97  	require.NotNil(t.T(), err)
    98  }
    99  
   100  func (t *testTCPReaderSuite) TestSyncGTID() {
   101  	var (
   102  		cfg  = replication.BinlogSyncerConfig{ServerID: serverIDs[1], Flavor: flavor}
   103  		gSet gmysql.GTIDSet // nil GTID set
   104  	)
   105  
   106  	// the first reader
   107  	r := NewTCPReader(cfg)
   108  	require.NotNil(t.T(), r)
   109  
   110  	// check status, stageNew
   111  	status := r.Status()
   112  	trStatus, ok := status.(*TCPReaderStatus)
   113  	require.True(t.T(), ok)
   114  	require.Equal(t.T(), common.StageNew.String(), trStatus.Stage)
   115  
   116  	// not prepared
   117  	e, err := r.GetEvent(context.Background())
   118  	require.NotNil(t.T(), err)
   119  	require.Nil(t.T(), e)
   120  
   121  	// nil GTID set
   122  	err = r.StartSyncByGTID(gSet)
   123  	require.NotNil(t.T(), err)
   124  
   125  	// empty GTID set
   126  	gSet, err = gtid.ParserGTID(flavor, "")
   127  	require.Nil(t.T(), err)
   128  
   129  	// prepare
   130  	err = r.StartSyncByGTID(gSet)
   131  	require.Nil(t.T(), err)
   132  
   133  	// re-prepare is invalid
   134  	err = r.StartSyncByGTID(gSet)
   135  	require.NotNil(t.T(), err)
   136  
   137  	// close the reader
   138  	err = r.Close()
   139  	require.Nil(t.T(), err)
   140  
   141  	// check status, stageClosed
   142  	status = r.Status()
   143  	trStatus, ok = status.(*TCPReaderStatus)
   144  	require.True(t.T(), ok)
   145  	require.Equal(t.T(), common.StageClosed.String(), trStatus.Stage)
   146  	require.Greater(t.T(), trStatus.ConnID, uint32(0))
   147  
   148  	// already closed
   149  	err = r.Close()
   150  	require.NotNil(t.T(), err)
   151  }