github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/pkg/dumpling/utils_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 dumpling 15 16 import ( 17 "context" 18 "os" 19 "path" 20 "strings" 21 "testing" 22 23 "github.com/go-mysql-org/go-mysql/mysql" 24 "github.com/pingcap/tidb/dumpling/export" 25 "github.com/pingcap/tiflow/dm/pkg/gtid" 26 "github.com/pingcap/tiflow/dm/pkg/log" 27 "github.com/pingcap/tiflow/dm/pkg/terror" 28 "github.com/stretchr/testify/require" 29 ) 30 31 func TestParseMetaData(t *testing.T) { 32 t.Parallel() 33 f, err := os.CreateTemp("", "metadata") 34 require.NoError(t, err) 35 defer os.Remove(f.Name()) 36 fdir := path.Dir(f.Name()) 37 fname := path.Base(f.Name()) 38 39 testCases := []struct { 40 source string 41 pos mysql.Position 42 gsetStr string 43 loc2 bool 44 pos2 mysql.Position 45 gsetStr2 string 46 }{ 47 { 48 `Started dump at: 2018-12-28 07:20:49 49 SHOW MASTER STATUS: 50 Log: bin.000001 51 Pos: 2479 52 GTID:97b5142f-e19c-11e8-808c-0242ac110005:1-13 53 54 Finished dump at: 2018-12-28 07:20:51`, 55 mysql.Position{ 56 Name: "bin.000001", 57 Pos: 2479, 58 }, 59 "97b5142f-e19c-11e8-808c-0242ac110005:1-13", 60 false, 61 mysql.Position{}, 62 "", 63 }, 64 { 65 `Started dump at: 2018-12-27 19:51:22 66 SHOW MASTER STATUS: 67 Log: mysql-bin.000003 68 Pos: 3295817 69 GTID: 70 71 SHOW SLAVE STATUS: 72 Host: 10.128.27.98 73 Log: mysql-bin.000003 74 Pos: 329635 75 GTID: 76 77 Finished dump at: 2018-12-27 19:51:22`, 78 mysql.Position{ 79 Name: "mysql-bin.000003", 80 Pos: 3295817, 81 }, 82 "", 83 false, 84 mysql.Position{}, 85 "", 86 }, 87 { // with empty line after multiple GTID sets 88 `Started dump at: 2020-05-21 18:14:49 89 SHOW MASTER STATUS: 90 Log: mysql-bin.000003 91 Pos: 1274 92 GTID:5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10, 93 5b642cb6-9b43-11ea-8914-0242ac170003:1-7, 94 97b5142f-e19c-11e8-808c-0242ac110005:1-13 95 96 SHOW SLAVE STATUS: 97 Host: 192.168.100.100 98 Log: mysql-bin.000003 99 Pos: 700 100 GTID:5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10, 101 5b642cb6-9b43-11ea-8914-0242ac170003:1-7, 102 97b5142f-e19c-11e8-808c-0242ac110005:1-13 103 104 Finished dump at: 2020-05-21 18:14:49`, 105 mysql.Position{ 106 Name: "mysql-bin.000003", 107 Pos: 1274, 108 }, 109 "5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,5b642cb6-9b43-11ea-8914-0242ac170003:1-7,97b5142f-e19c-11e8-808c-0242ac110005:1-13", 110 false, 111 mysql.Position{}, 112 "", 113 }, 114 { // without empty line after mutlple GTID sets 115 `Started dump at: 2020-05-21 18:02:33 116 SHOW MASTER STATUS: 117 Log: mysql-bin.000003 118 Pos: 1274 119 GTID:5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10, 120 5b642cb6-9b43-11ea-8914-0242ac170003:1-7, 121 97b5142f-e19c-11e8-808c-0242ac110005:1-13 122 Finished dump at: 2020-05-21 18:02:44`, 123 mysql.Position{ 124 Name: "mysql-bin.000003", 125 Pos: 1274, 126 }, 127 "5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,5b642cb6-9b43-11ea-8914-0242ac170003:1-7,97b5142f-e19c-11e8-808c-0242ac110005:1-13", 128 false, 129 mysql.Position{}, 130 "", 131 }, 132 { // with empty line after multiple GTID sets 133 `Started dump at: 2020-05-21 18:14:49 134 SHOW MASTER STATUS: 135 Log: mysql-bin.000003 136 Pos: 1274 137 GTID:5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10, 138 5b642cb6-9b43-11ea-8914-0242ac170003:1-7, 139 97b5142f-e19c-11e8-808c-0242ac110005:1-13 140 141 SHOW SLAVE STATUS: 142 Host: 192.168.100.100 143 Log: mysql-bin.000003 144 Pos: 700 145 GTID:5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10, 146 5b642cb6-9b43-11ea-8914-0242ac170003:1-7, 147 97b5142f-e19c-11e8-808c-0242ac110005:1-13 148 149 SHOW MASTER STATUS: /* AFTER CONNECTION POOL ESTABLISHED */ 150 Log: mysql-bin.000003 151 Pos: 1280 152 GTID:5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10, 153 5b642cb6-9b43-11ea-8914-0242ac170003:1-7, 154 97b5142f-e19c-11e8-808c-0242ac110005:1-14 155 156 Finished dump at: 2020-05-21 18:14:49`, 157 mysql.Position{ 158 Name: "mysql-bin.000003", 159 Pos: 1274, 160 }, 161 "5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,5b642cb6-9b43-11ea-8914-0242ac170003:1-7,97b5142f-e19c-11e8-808c-0242ac110005:1-13", 162 true, 163 mysql.Position{ 164 Name: "mysql-bin.000003", 165 Pos: 1280, 166 }, 167 "5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,5b642cb6-9b43-11ea-8914-0242ac170003:1-7,97b5142f-e19c-11e8-808c-0242ac110005:1-14", 168 }, 169 { // with empty line after multiple GTID sets 170 `Started dump at: 2020-05-21 18:14:49 171 SHOW MASTER STATUS: 172 Log: mysql-bin.000003 173 Pos: 1274 174 GTID:5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10, 175 5b642cb6-9b43-11ea-8914-0242ac170003:1-7, 176 97b5142f-e19c-11e8-808c-0242ac110005:1-13 177 178 SHOW SLAVE STATUS: 179 Host: 192.168.100.100 180 Log: mysql-bin.000003 181 Pos: 700 182 GTID:5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10, 183 5b642cb6-9b43-11ea-8914-0242ac170003:1-7, 184 97b5142f-e19c-11e8-808c-0242ac110005:1-13 185 186 SHOW MASTER STATUS: /* AFTER CONNECTION POOL ESTABLISHED */ 187 Log: mysql-bin.000004 188 Pos: 4 189 GTID:5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10, 190 5b642cb6-9b43-11ea-8914-0242ac170003:1-9, 191 97b5142f-e19c-11e8-808c-0242ac110005:1-13 192 193 Finished dump at: 2020-05-21 18:14:49`, 194 mysql.Position{ 195 Name: "mysql-bin.000003", 196 Pos: 1274, 197 }, 198 "5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,5b642cb6-9b43-11ea-8914-0242ac170003:1-7,97b5142f-e19c-11e8-808c-0242ac110005:1-13", 199 true, 200 mysql.Position{ 201 Name: "mysql-bin.000004", 202 Pos: 4, 203 }, 204 "5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,5b642cb6-9b43-11ea-8914-0242ac170003:1-9,97b5142f-e19c-11e8-808c-0242ac110005:1-13", 205 }, 206 { // no GTID sets 207 `Started dump at: 2020-09-30 12:16:49 208 SHOW MASTER STATUS: 209 Log: mysql-bin-changelog.000003 210 Pos: 12470000 211 212 SHOW MASTER STATUS: /* AFTER CONNECTION POOL ESTABLISHED */ 213 Log: mysql-bin-changelog.000003 214 Pos: 12470000 215 216 Finished dump at: 2020-09-30 12:16:49 217 `, 218 mysql.Position{ 219 Name: "mysql-bin-changelog.000003", 220 Pos: 12470000, 221 }, 222 "", 223 true, 224 mysql.Position{ 225 Name: "mysql-bin-changelog.000003", 226 Pos: 12470000, 227 }, 228 "", 229 }, 230 } 231 ctx := context.Background() 232 for _, tc := range testCases { 233 err2 := os.WriteFile(f.Name(), []byte(tc.source), 0o644) 234 require.NoError(t, err2) 235 loc, loc2, err2 := ParseMetaData(ctx, fdir, fname, nil) 236 require.NoError(t, err2) 237 require.Equal(t, tc.pos, loc.Position) 238 gs, _ := gtid.ParserGTID("mysql", tc.gsetStr) 239 require.Equal(t, gs, loc.GetGTID()) 240 if tc.loc2 { 241 require.Equal(t, tc.pos2, loc2.Position) 242 gs2, _ := gtid.ParserGTID("mysql", tc.gsetStr2) 243 require.Equal(t, gs2, loc2.GetGTID()) 244 } else { 245 require.Nil(t, loc2) 246 } 247 } 248 249 noBinlogLoc := `Started dump at: 2020-12-02 17:13:56 250 Finished dump at: 2020-12-02 17:13:56 251 ` 252 err = os.WriteFile(f.Name(), []byte(noBinlogLoc), 0o644) 253 require.NoError(t, err) 254 _, _, err = ParseMetaData(ctx, fdir, fname, nil) 255 require.True(t, terror.ErrMetadataNoBinlogLoc.Equal(err)) 256 } 257 258 func TestParseArgs(t *testing.T) { 259 t.Parallel() 260 logger := log.L() 261 262 exportCfg := export.DefaultConfig() 263 extraArgs := `--statement-size=100 --where t>10 --threads 8 -F 50B` 264 err := ParseExtraArgs(&logger, exportCfg, strings.Fields(extraArgs)) 265 require.NoError(t, err) 266 require.Equal(t, uint64(100), exportCfg.StatementSize) 267 require.Equal(t, "t>10", exportCfg.Where) 268 require.Equal(t, 8, exportCfg.Threads) 269 require.Equal(t, uint64(50), exportCfg.FileSize) 270 271 extraArgs = `--threads 16 --skip-tz-utc` 272 err = ParseExtraArgs(&logger, exportCfg, strings.Fields(extraArgs)) 273 require.Error(t, err) 274 require.Equal(t, 16, exportCfg.Threads) 275 require.Equal(t, uint64(100), exportCfg.StatementSize) 276 277 // no `--tables-list` or `--filter` specified, match anything 278 require.True(t, exportCfg.TableFilter.MatchTable("foo", "bar")) 279 require.True(t, exportCfg.TableFilter.MatchTable("bar", "foo")) 280 281 // specify `--tables-list`. 282 extraArgs = `--threads 16 --tables-list=foo.bar` 283 err = ParseExtraArgs(&logger, exportCfg, strings.Fields(extraArgs)) 284 require.NoError(t, err) 285 require.True(t, exportCfg.TableFilter.MatchTable("foo", "bar")) 286 require.False(t, exportCfg.TableFilter.MatchTable("bar", "foo")) 287 288 // specify `--tables-list` and `--filter` 289 extraArgs = `--threads 16 --tables-list=foo.bar --filter=*.foo` 290 err = ParseExtraArgs(&logger, exportCfg, strings.Fields(extraArgs)) 291 require.Regexp(t, ".*--tables-list and --filter together.*", err) 292 293 // only specify `--filter`. 294 extraArgs = `--threads 16 --filter=*.foo` 295 err = ParseExtraArgs(&logger, exportCfg, strings.Fields(extraArgs)) 296 require.NoError(t, err) 297 require.False(t, exportCfg.TableFilter.MatchTable("foo", "bar")) 298 require.True(t, exportCfg.TableFilter.MatchTable("bar", "foo")) 299 300 // compatibility for `--no-locks` 301 extraArgs = `--no-locks` 302 err = ParseExtraArgs(&logger, exportCfg, strings.Fields(extraArgs)) 303 require.NoError(t, err) 304 require.Equal(t, "none", exportCfg.Consistency) 305 306 // compatibility for `--no-locks` 307 extraArgs = `--no-locks --consistency none` 308 err = ParseExtraArgs(&logger, exportCfg, strings.Fields(extraArgs)) 309 require.NoError(t, err) 310 require.Equal(t, "none", exportCfg.Consistency) 311 312 extraArgs = `--consistency lock` 313 err = ParseExtraArgs(&logger, exportCfg, strings.Fields(extraArgs)) 314 require.NoError(t, err) 315 require.Equal(t, "lock", exportCfg.Consistency) 316 317 // compatibility for `--no-locks` 318 extraArgs = `--no-locks --consistency lock` 319 err = ParseExtraArgs(&logger, exportCfg, strings.Fields(extraArgs)) 320 require.Equal(t, "cannot both specify `--no-locks` and `--consistency` other than `none`", err.Error()) 321 }