github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/relay/util_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 relay 15 16 import ( 17 "context" 18 "fmt" 19 "io" 20 21 "github.com/DATA-DOG/go-sqlmock" 22 gmysql "github.com/go-mysql-org/go-mysql/mysql" 23 . "github.com/pingcap/check" 24 "github.com/pingcap/errors" 25 "github.com/pingcap/tiflow/dm/pkg/conn" 26 tcontext "github.com/pingcap/tiflow/dm/pkg/context" 27 "github.com/pingcap/tiflow/dm/pkg/log" 28 ) 29 30 var _ = Suite(&testUtilSuite{}) 31 32 type testUtilSuite struct{} 33 34 func (t *testUtilSuite) TestIsNewServer(c *C) { 35 ctx, cancel := context.WithTimeout(context.Background(), conn.DefaultDBTimeout) 36 defer cancel() 37 38 mockDB := conn.InitMockDB(c) 39 baseDB, err := conn.GetUpstreamDB(getDBConfigForTest()) 40 c.Assert(err, IsNil) 41 42 flavor := gmysql.MySQLFlavor 43 // no prevUUID, is new server. 44 isNew, err := isNewServer(ctx, "", baseDB, flavor) 45 c.Assert(err, IsNil) 46 c.Assert(isNew, IsTrue) 47 48 // different server 49 mockGetServerUUID(mockDB) 50 isNew, err = isNewServer(ctx, "not-exists-uuid.000001", baseDB, flavor) 51 c.Assert(err, IsNil) 52 c.Assert(isNew, IsTrue) 53 54 // the same server 55 mockGetServerUUID(mockDB) 56 currUUID, err := conn.GetServerUUID(tcontext.NewContext(ctx, log.L()), baseDB, flavor) 57 c.Assert(err, IsNil) 58 59 mockGetServerUUID(mockDB) 60 isNew, err = isNewServer(ctx, fmt.Sprintf("%s.000001", currUUID), baseDB, flavor) 61 c.Assert(err, IsNil) 62 c.Assert(isNew, IsFalse) 63 c.Assert(mockDB.ExpectationsWereMet(), IsNil) 64 } 65 66 func mockGetServerUUID(mockDB sqlmock.Sqlmock) { 67 mockDB.ExpectQuery("SHOW GLOBAL VARIABLES LIKE 'server_uuid'").WithArgs(). 68 WillReturnRows(sqlmock.NewRows([]string{"Variable_name", "Value"}).AddRow("server_uuid", "12e57f06-f360-11eb-8235-585cc2bc66c9")) 69 } 70 71 func mockGetRandomServerID(mockDB sqlmock.Sqlmock) { 72 rows := sqlmock.NewRows([]string{"Server_id", "Host", "Port", "Master_id", "Slave_UUID"}) 73 rows.AddRow("2", "127.0.0.1", "3307", "1", "uuid2") 74 mockDB.ExpectQuery("SHOW SLAVE HOSTS").WillReturnRows(rows) 75 mockDB.ExpectQuery("SHOW GLOBAL VARIABLES LIKE 'server_id'").WillReturnRows( 76 sqlmock.NewRows([]string{"Variable_name", "Value"}).AddRow("server_id", "1")) 77 } 78 79 func (t *testUtilSuite) TestGetNextUUID(c *C) { 80 UUIDs := []string{ 81 "b60868af-5a6f-11e9-9ea3-0242ac160006.000001", 82 "7acfedb5-3008-4fa2-9776-6bac42b025fe.000002", 83 "92ffd03b-813e-4391-b16a-177524e8d531.000003", 84 "338513ce-b24e-4ff8-9ded-9ac5aa8f4d74.000004", 85 } 86 cases := []struct { 87 currUUID string 88 UUIDs []string 89 nextUUID string 90 nextUUIDSuffix string 91 errMsgReg string 92 }{ 93 { 94 // empty current and UUID list 95 }, 96 { 97 // non-empty current UUID, but empty UUID list 98 currUUID: "b60868af-5a6f-11e9-9ea3-0242ac160006.000001", 99 }, 100 { 101 // empty current UUID, but non-empty UUID list 102 UUIDs: UUIDs, 103 }, 104 { 105 // current UUID in UUID list, has next UUID 106 currUUID: UUIDs[0], 107 UUIDs: UUIDs, 108 nextUUID: UUIDs[1], 109 nextUUIDSuffix: UUIDs[1][len(UUIDs[1])-6:], 110 }, 111 { 112 // current UUID in UUID list, but has no next UUID 113 currUUID: UUIDs[len(UUIDs)-1], 114 UUIDs: UUIDs, 115 }, 116 { 117 // current UUID not in UUID list 118 currUUID: "40ed16c1-f6f7-4012-aa9b-d360261d2b22.666666", 119 UUIDs: UUIDs, 120 }, 121 { 122 // invalid next UUID in UUID list 123 currUUID: UUIDs[len(UUIDs)-1], 124 UUIDs: append(UUIDs, "invalid-uuid"), 125 errMsgReg: ".*invalid-uuid.*", 126 }, 127 } 128 129 for _, cs := range cases { 130 nu, nus, err := getNextRelaySubDir(cs.currUUID, cs.UUIDs) 131 if len(cs.errMsgReg) > 0 { 132 c.Assert(err, ErrorMatches, cs.errMsgReg) 133 } else { 134 c.Assert(err, IsNil) 135 } 136 c.Assert(nu, Equals, cs.nextUUID) 137 c.Assert(nus, Equals, cs.nextUUIDSuffix) 138 } 139 } 140 141 func (t *testUtilSuite) TestIsIgnorableParseError(c *C) { 142 cases := []struct { 143 err error 144 ignorable bool 145 }{ 146 { 147 err: nil, 148 ignorable: false, 149 }, 150 { 151 err: io.EOF, 152 ignorable: true, 153 }, 154 { 155 err: errors.Annotate(io.EOF, "annotated end of file"), 156 ignorable: true, 157 }, 158 { 159 err: errors.New("get event header err EOF xxxx"), 160 ignorable: true, 161 }, 162 { 163 err: errors.New("some other error"), 164 ignorable: false, 165 }, 166 } 167 168 for _, cs := range cases { 169 c.Assert(isIgnorableParseError(cs.err), Equals, cs.ignorable) 170 } 171 }