github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/pkg/checker/binlog_test.go (about) 1 // Copyright 2022 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 package checker 14 15 import ( 16 "context" 17 "testing" 18 19 "github.com/DATA-DOG/go-sqlmock" 20 "github.com/pingcap/tidb/pkg/util/dbutil" 21 "github.com/pingcap/tiflow/dm/pkg/conn" 22 "github.com/stretchr/testify/require" 23 ) 24 25 func TestBinlogDB(t *testing.T) { 26 db, mock, err := sqlmock.New() 27 require.Nil(t, err) 28 ctx := context.Background() 29 30 cases := []struct { 31 doDB string 32 ignoreDB string 33 schemas map[string]struct{} 34 state State 35 caseSensitive bool 36 }{ 37 // doDB 38 { 39 doDB: "do", 40 schemas: map[string]struct{}{ 41 "do": {}, 42 }, 43 state: StateSuccess, 44 }, 45 { 46 doDB: "do", 47 schemas: map[string]struct{}{ 48 "do": {}, 49 "do2": {}, 50 }, 51 state: StateFailure, 52 }, 53 { 54 doDB: "do", 55 schemas: map[string]struct{}{ 56 "do2": {}, 57 }, 58 state: StateFailure, 59 }, 60 { 61 doDB: "do,do2", 62 schemas: map[string]struct{}{ 63 "do2": {}, 64 }, 65 state: StateSuccess, 66 }, 67 // ignoreDB 68 { 69 ignoreDB: "ignore", 70 schemas: map[string]struct{}{ 71 "do": {}, 72 "ignore": {}, 73 }, 74 state: StateFailure, 75 }, 76 { 77 ignoreDB: "ignore", 78 schemas: map[string]struct{}{ 79 "do": {}, 80 "do2": {}, 81 }, 82 state: StateSuccess, 83 }, 84 { 85 ignoreDB: "ignore,ignore2", 86 schemas: map[string]struct{}{ 87 "do": {}, 88 "ignore2": {}, 89 }, 90 state: StateFailure, 91 }, 92 { 93 ignoreDB: "ignore,ignore2", 94 schemas: map[string]struct{}{ 95 "ignore3": {}, 96 }, 97 state: StateSuccess, 98 }, 99 // case sensitive 100 { 101 caseSensitive: true, 102 doDB: "Do", 103 schemas: map[string]struct{}{ 104 "do": {}, 105 }, 106 state: StateFailure, 107 }, 108 { 109 caseSensitive: false, 110 doDB: "Do", 111 schemas: map[string]struct{}{ 112 "do": {}, 113 }, 114 state: StateSuccess, 115 }, 116 } 117 118 for _, cs := range cases { 119 binlogDBChecker := NewBinlogDBChecker(conn.NewBaseDBForTest(db), &dbutil.DBConfig{}, cs.schemas, cs.caseSensitive) 120 versionRow := sqlmock.NewRows([]string{"Variable_name", "Value"}).AddRow("version", "mysql") 121 masterStatusRow := sqlmock.NewRows([]string{"File", "Position", "Binlog_Do_DB", "Binlog_Ignore_DB", "Executed_Gtid_Set"}). 122 AddRow("", 0, cs.doDB, cs.ignoreDB, "") 123 mock.ExpectQuery("SHOW GLOBAL VARIABLES LIKE 'version'").WillReturnRows(versionRow) 124 mock.ExpectQuery("SHOW MASTER STATUS").WillReturnRows(masterStatusRow) 125 126 r := binlogDBChecker.Check(ctx) 127 require.Nil(t, mock.ExpectationsWereMet()) 128 require.Equal(t, cs.state, r.State) 129 // the error message is moved to Errors 130 if r.State == StateFailure { 131 require.Equal(t, 1, len(r.Errors)) 132 } 133 } 134 } 135 136 func TestMySQLBinlogRowImageChecker(t *testing.T) { 137 db, mock, err := sqlmock.New() 138 require.Nil(t, err) 139 ctx := context.Background() 140 141 cases := []struct { 142 version string 143 state State 144 needCheck bool 145 rowImage string 146 }{ 147 // mysql < 5.6.2 don't need check 148 { 149 version: "5.6.1-log", 150 state: StateSuccess, 151 needCheck: false, 152 rowImage: "", 153 }, 154 // mysql >= 5.6.2 need check - success 155 { 156 version: "5.6.2-log", 157 state: StateSuccess, 158 needCheck: true, 159 rowImage: "full", 160 }, 161 // mysql >= 5.6.2 need check - failed 162 { 163 version: "5.6.2-log", 164 state: StateFailure, 165 needCheck: true, 166 rowImage: "NOBLOB", 167 }, 168 169 // mariadb < 10.1.6 don't need check 170 { 171 version: "10.1.5-MariaDB-1~wheezy", 172 state: StateSuccess, 173 needCheck: false, 174 rowImage: "", 175 }, 176 177 // mariadb >= 10.1.6 need check - success 178 { 179 version: "10.1.6-MariaDB-1~wheezy", 180 state: StateSuccess, 181 needCheck: true, 182 rowImage: "full", 183 }, 184 // mariadb >= 10.1.6 need check - failed 185 { 186 version: "10.1.6-MariaDB-1~wheezy", 187 state: StateFailure, 188 needCheck: true, 189 rowImage: "NOBLOB", 190 }, 191 } 192 193 for _, cs := range cases { 194 binlogDBChecker := NewMySQLBinlogRowImageChecker(db, &dbutil.DBConfig{}) 195 versionRow := sqlmock.NewRows([]string{"Variable_name", "Value"}).AddRow("version", cs.version) 196 mock.ExpectQuery("SHOW GLOBAL VARIABLES LIKE 'version'").WillReturnRows(versionRow) 197 if cs.needCheck { 198 binlogRowImageRow := sqlmock.NewRows([]string{"Variable_name", "Value"}).AddRow("binlog_row_image", cs.rowImage) 199 mock.ExpectQuery("SHOW GLOBAL VARIABLES LIKE 'binlog_row_image'").WillReturnRows(binlogRowImageRow) 200 } 201 r := binlogDBChecker.Check(ctx) 202 require.Nil(t, mock.ExpectationsWereMet()) 203 require.Equal(t, cs.state, r.State) 204 } 205 }