github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/pkg/v1dbschema/schema_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 v1dbschema
    15  
    16  import (
    17  	"fmt"
    18  	"os"
    19  	"strconv"
    20  	"testing"
    21  
    22  	"github.com/DATA-DOG/go-sqlmock"
    23  	gmysql "github.com/go-mysql-org/go-mysql/mysql"
    24  	. "github.com/pingcap/check"
    25  	"github.com/pingcap/failpoint"
    26  	"github.com/pingcap/tiflow/dm/config"
    27  	"github.com/pingcap/tiflow/dm/config/dbconfig"
    28  	"github.com/pingcap/tiflow/dm/pkg/conn"
    29  	tcontext "github.com/pingcap/tiflow/dm/pkg/context"
    30  	"github.com/pingcap/tiflow/dm/pkg/gtid"
    31  )
    32  
    33  func TestSuite(t *testing.T) {
    34  	TestingT(t)
    35  }
    36  
    37  type testSchema struct {
    38  	host     string
    39  	port     int
    40  	user     string
    41  	password string
    42  	db       *conn.BaseDB
    43  	mockDB   sqlmock.Sqlmock
    44  }
    45  
    46  var _ = Suite(&testSchema{})
    47  
    48  func (t *testSchema) SetUpSuite(c *C) {
    49  	t.setUpDBConn(c)
    50  }
    51  
    52  func (t *testSchema) TestTearDown(c *C) {
    53  	t.db.Close()
    54  }
    55  
    56  func (t *testSchema) setUpDBConn(c *C) {
    57  	t.host = os.Getenv("MYSQL_HOST")
    58  	if t.host == "" {
    59  		t.host = "127.0.0.1"
    60  	}
    61  	t.port, _ = strconv.Atoi(os.Getenv("MYSQL_PORT"))
    62  	if t.port == 0 {
    63  		t.port = 3306
    64  	}
    65  	t.user = os.Getenv("MYSQL_USER")
    66  	if t.user == "" {
    67  		t.user = "root"
    68  	}
    69  	t.password = os.Getenv("MYSQL_PSWD")
    70  
    71  	cfg := &dbconfig.DBConfig{
    72  		Host:     t.host,
    73  		Port:     t.port,
    74  		User:     t.user,
    75  		Password: t.password,
    76  		Session:  map[string]string{"sql_log_bin": "off"}, // do not enable binlog to break other unit test cases.
    77  	}
    78  	cfg.Adjust()
    79  
    80  	var err error
    81  	t.mockDB = conn.InitMockDB(c)
    82  	t.db, err = conn.GetUpstreamDB(cfg)
    83  	c.Assert(err, IsNil)
    84  }
    85  
    86  func (t *testSchema) TestSchemaV106ToV20x(c *C) {
    87  	var (
    88  		tctx = tcontext.Background()
    89  		cfg  = &config.SubTaskConfig{
    90  			Name:       "test",
    91  			SourceID:   "mysql-replica-01",
    92  			ServerID:   429523137,
    93  			MetaSchema: "dm_meta_v106_test",
    94  			From: dbconfig.DBConfig{
    95  				Host:     t.host,
    96  				Port:     t.port,
    97  				User:     t.user,
    98  				Password: t.password,
    99  			},
   100  		}
   101  		endGS, _ = gtid.ParserGTID(gmysql.MySQLFlavor, "ccb992ad-a557-11ea-ba6a-0242ac140002:1-16")
   102  	)
   103  
   104  	c.Assert(failpoint.Enable("github.com/pingcap/tiflow/dm/pkg/v1dbschema/MockGetGTIDsForPos", `return("ccb992ad-a557-11ea-ba6a-0242ac140002:10-16")`), IsNil)
   105  	//nolint:errcheck
   106  	defer failpoint.Disable("github.com/pingcap/tiflow/dm/pkg/v1dbschema/MockGetGTIDsForPos")
   107  	c.Assert(failpoint.Enable("github.com/pingcap/tiflow/dm/pkg/conn/GetGTIDPurged", `return("ccb992ad-a557-11ea-ba6a-0242ac140002:1-9")`), IsNil)
   108  	//nolint:errcheck
   109  	defer failpoint.Disable("github.com/pingcap/tiflow/dm/pkg/conn/GetGTIDPurged")
   110  
   111  	// update schema without GTID enabled.
   112  	// mock updateSyncerCheckpoint
   113  	t.mockDB.ExpectBegin()
   114  	t.mockDB.ExpectExec("ALTER TABLE `dm_meta_v106_test`.`test_syncer_checkpoint` ADD COLUMN binlog_gtid TEXT AFTER binlog_pos").WithArgs().WillReturnResult(sqlmock.NewErrorResult(nil))
   115  	t.mockDB.ExpectExec("ALTER TABLE `dm_meta_v106_test`.`test_syncer_checkpoint` ADD COLUMN table_info JSON NOT NULL AFTER binlog_gtid").WithArgs().WillReturnResult(sqlmock.NewErrorResult(nil))
   116  	t.mockDB.ExpectCommit()
   117  	// mock updateSyncerOnlineDDLMeta
   118  	t.mockDB.ExpectBegin()
   119  	t.mockDB.ExpectExec("UPDATE `dm_meta_v106_test`.`test_onlineddl`.*").WithArgs(cfg.SourceID, fmt.Sprint(cfg.ServerID)).WillReturnResult(sqlmock.NewErrorResult(nil))
   120  	t.mockDB.ExpectCommit()
   121  	c.Assert(UpdateSchema(tctx, t.db, cfg), IsNil)
   122  	c.Assert(t.mockDB.ExpectationsWereMet(), IsNil)
   123  
   124  	// update schema with GTID enabled.
   125  	cfg.EnableGTID = true
   126  	// reset mockDB conn because last UpdateSchema would close the conn.
   127  	t.setUpDBConn(c)
   128  	// mock updateSyncerCheckpoint
   129  	t.mockDB.ExpectQuery("SELECT binlog_name, binlog_pos FROM `dm_meta_v106_test`.`test_syncer_checkpoint`.*").
   130  		WithArgs(cfg.SourceID, true).WillReturnRows(sqlmock.NewRows([]string{"binlog_name", "binlog_pos"}).
   131  		AddRow("mysql-bin.000001", "0"))
   132  	t.mockDB.ExpectBegin()
   133  	t.mockDB.ExpectExec("ALTER TABLE `dm_meta_v106_test`.`test_syncer_checkpoint` ADD COLUMN binlog_gtid TEXT AFTER binlog_pos").WithArgs().WillReturnResult(sqlmock.NewErrorResult(nil))
   134  	t.mockDB.ExpectExec("ALTER TABLE `dm_meta_v106_test`.`test_syncer_checkpoint` ADD COLUMN table_info JSON NOT NULL AFTER binlog_gtid").WithArgs().WillReturnResult(sqlmock.NewErrorResult(nil))
   135  	t.mockDB.ExpectCommit()
   136  	t.mockDB.ExpectBegin()
   137  	t.mockDB.ExpectExec("UPDATE `dm_meta_v106_test`.`test_syncer_checkpoint` SET binlog_gtid.*").
   138  		WithArgs(endGS.String(), cfg.SourceID, true).WillReturnResult(sqlmock.NewErrorResult(nil))
   139  	t.mockDB.ExpectCommit()
   140  	// mock updateSyncerOnlineDDLMeta
   141  	t.mockDB.ExpectBegin()
   142  	t.mockDB.ExpectExec("UPDATE `dm_meta_v106_test`.`test_onlineddl`.*").WithArgs(cfg.SourceID, fmt.Sprint(cfg.ServerID)).WillReturnResult(sqlmock.NewErrorResult(nil))
   143  	t.mockDB.ExpectCommit()
   144  	c.Assert(UpdateSchema(tctx, t.db, cfg), IsNil)
   145  	c.Assert(t.mockDB.ExpectationsWereMet(), IsNil)
   146  }