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 }