github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/syncer/sharding-meta/shardmeta_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 shardmeta 15 16 import ( 17 "fmt" 18 "testing" 19 20 "github.com/go-mysql-org/go-mysql/mysql" 21 "github.com/pingcap/check" 22 "github.com/pingcap/tiflow/dm/pkg/binlog" 23 ) 24 25 var _ = check.Suite(&testShardMetaSuite{}) 26 27 func TestSuite(t *testing.T) { 28 check.TestingT(t) 29 } 30 31 type testShardMetaSuite struct{} 32 33 func (t *testShardMetaSuite) TestShardingMeta(c *check.C) { 34 var ( 35 active bool 36 err error 37 sqls []string 38 args [][]interface{} 39 location binlog.Location 40 filename = "mysql-bin.000001" 41 table1 = "table1" 42 table2 = "table2" 43 table3 = "table3" 44 metaSchema = "dm_meta" 45 metaTable = "test_syncer_sharding_meta" 46 sourceID = "mysql-replica-01" 47 tableID = "`target_db`.`target_table`" 48 meta = NewShardingMeta(metaSchema, metaTable, false) 49 items = []*DDLItem{ 50 NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1000}}, []string{"ddl1"}, table1), 51 NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1200}}, []string{"ddl2-1,ddl2-2"}, table1), 52 NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1400}}, []string{"ddl3"}, table1), 53 NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1600}}, []string{"ddl1"}, table2), 54 NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1800}}, []string{"ddl2-1,ddl2-2"}, table2), 55 NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 2000}}, []string{"ddl3"}, table2), 56 NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 2200}}, []string{"ddl1"}, table3), 57 NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 2400}}, []string{"ddl2-1,ddl2-2"}, table3), 58 NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 2600}}, []string{"ddl3"}, table3), 59 } 60 ) 61 62 // 1st round sharding DDL sync 63 for i := 0; i < 7; i++ { 64 active, err = meta.AddItem(items[i]) 65 c.Assert(err, check.IsNil) 66 if i%3 == 0 { 67 c.Assert(active, check.IsTrue) 68 } else { 69 c.Assert(active, check.IsFalse) 70 } 71 } 72 73 c.Assert(meta.GetGlobalItems(), check.DeepEquals, []*DDLItem{items[0], items[1], items[2]}) 74 c.Assert(meta.GetGlobalActiveDDL(), check.DeepEquals, items[0]) 75 c.Assert(meta.GetActiveDDLItem(table1), check.DeepEquals, items[0]) 76 c.Assert(meta.GetActiveDDLItem(table2), check.DeepEquals, items[3]) 77 c.Assert(meta.GetActiveDDLItem(table3), check.DeepEquals, items[6]) 78 c.Assert(meta.InSequenceSharding(), check.IsTrue) 79 location, err = meta.ActiveDDLFirstLocation() 80 c.Assert(err, check.IsNil) 81 c.Assert(location.Position, check.DeepEquals, items[0].FirstLocation.Position) 82 83 // find synced in shrading group, and call ShardingMeta.ResolveShardingDDL 84 c.Assert(meta.ResolveShardingDDL(), check.IsFalse) 85 86 c.Assert(meta.GetGlobalActiveDDL(), check.DeepEquals, items[1]) 87 c.Assert(meta.GetActiveDDLItem(table1), check.DeepEquals, items[1]) 88 c.Assert(meta.GetActiveDDLItem(table2), check.DeepEquals, items[4]) 89 c.Assert(meta.GetActiveDDLItem(table3), check.IsNil) 90 c.Assert(meta.InSequenceSharding(), check.IsTrue) 91 location, err = meta.ActiveDDLFirstLocation() 92 c.Assert(err, check.IsNil) 93 c.Assert(location.Position, check.DeepEquals, items[1].FirstLocation.Position) 94 95 sqls, args = meta.FlushData(sourceID, tableID) 96 c.Assert(sqls, check.HasLen, 4) 97 c.Assert(args, check.HasLen, 4) 98 for _, stmt := range sqls { 99 c.Assert(stmt, check.Matches, "INSERT INTO .*") 100 } 101 for _, arg := range args { 102 c.Assert(arg, check.HasLen, 8) 103 c.Assert(arg[3], check.Equals, 1) 104 } 105 106 // 2nd round sharding DDL sync 107 for i := 0; i < 8; i++ { 108 if i%3 == 0 { 109 continue 110 } 111 active, err = meta.AddItem(items[i]) 112 c.Assert(err, check.IsNil) 113 if i%3 == 1 { 114 c.Assert(active, check.IsTrue) 115 } else { 116 c.Assert(active, check.IsFalse) 117 } 118 } 119 120 c.Assert(meta.GetGlobalActiveDDL(), check.DeepEquals, items[1]) 121 c.Assert(meta.GetActiveDDLItem(table1), check.DeepEquals, items[1]) 122 c.Assert(meta.GetActiveDDLItem(table2), check.DeepEquals, items[4]) 123 c.Assert(meta.GetActiveDDLItem(table3), check.DeepEquals, items[7]) 124 c.Assert(meta.InSequenceSharding(), check.IsTrue) 125 location, err = meta.ActiveDDLFirstLocation() 126 c.Assert(err, check.IsNil) 127 c.Assert(location.Position, check.DeepEquals, items[1].FirstLocation.Position) 128 129 // find synced in shrading group, and call ShardingMeta.ResolveShardingDDL 130 c.Assert(meta.ResolveShardingDDL(), check.IsFalse) 131 132 c.Assert(meta.GetGlobalActiveDDL(), check.DeepEquals, items[2]) 133 c.Assert(meta.GetActiveDDLItem(table1), check.DeepEquals, items[2]) 134 c.Assert(meta.GetActiveDDLItem(table2), check.DeepEquals, items[5]) 135 c.Assert(meta.GetActiveDDLItem(table3), check.IsNil) 136 c.Assert(meta.InSequenceSharding(), check.IsTrue) 137 location, err = meta.ActiveDDLFirstLocation() 138 c.Assert(err, check.IsNil) 139 c.Assert(location.Position, check.DeepEquals, items[2].FirstLocation.Position) 140 141 sqls, args = meta.FlushData(sourceID, tableID) 142 c.Assert(sqls, check.HasLen, 4) 143 c.Assert(args, check.HasLen, 4) 144 for _, stmt := range sqls { 145 c.Assert(stmt, check.Matches, "INSERT INTO .*") 146 } 147 for _, arg := range args { 148 c.Assert(arg, check.HasLen, 8) 149 c.Assert(arg[3], check.Equals, 2) 150 } 151 152 // 3rd round sharding DDL sync 153 for i := 0; i < 9; i++ { 154 if i%3 != 2 { 155 continue 156 } 157 active, err = meta.AddItem(items[i]) 158 c.Assert(err, check.IsNil) 159 if i%3 == 2 { 160 c.Assert(active, check.IsTrue) 161 } else { 162 c.Assert(active, check.IsFalse) 163 } 164 } 165 c.Assert(meta.GetGlobalActiveDDL(), check.DeepEquals, items[2]) 166 c.Assert(meta.GetActiveDDLItem(table1), check.DeepEquals, items[2]) 167 c.Assert(meta.GetActiveDDLItem(table2), check.DeepEquals, items[5]) 168 c.Assert(meta.GetActiveDDLItem(table3), check.DeepEquals, items[8]) 169 c.Assert(meta.InSequenceSharding(), check.IsTrue) 170 location, err = meta.ActiveDDLFirstLocation() 171 c.Assert(err, check.IsNil) 172 c.Assert(location.Position, check.DeepEquals, items[2].FirstLocation.Position) 173 174 // find synced in shrading group, and call ShardingMeta.ResolveShardingDDL 175 c.Assert(meta.ResolveShardingDDL(), check.IsTrue) 176 177 c.Assert(meta.GetGlobalActiveDDL(), check.IsNil) 178 c.Assert(meta.GetActiveDDLItem(table1), check.IsNil) 179 c.Assert(meta.GetActiveDDLItem(table2), check.IsNil) 180 c.Assert(meta.GetActiveDDLItem(table3), check.IsNil) 181 c.Assert(meta.InSequenceSharding(), check.IsFalse) 182 _, err = meta.ActiveDDLFirstLocation() 183 c.Assert(err, check.ErrorMatches, fmt.Sprintf("\\[.*\\], Message: activeIdx %d larger than length of global DDLItems: .*", meta.ActiveIdx())) 184 185 sqls, args = meta.FlushData(sourceID, tableID) 186 c.Assert(sqls, check.HasLen, 1) 187 c.Assert(args, check.HasLen, 1) 188 c.Assert(sqls[0], check.Matches, "DELETE FROM .*") 189 c.Assert(args[0], check.DeepEquals, []interface{}{sourceID, tableID}) 190 } 191 192 func (t *testShardMetaSuite) TestShardingMetaWrongSequence(c *check.C) { 193 var ( 194 active bool 195 err error 196 filename = "mysql-bin.000001" 197 table1 = "table1" 198 table2 = "table2" 199 meta = NewShardingMeta("", "", false) 200 items = []*DDLItem{ 201 NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1000}}, []string{"ddl1"}, table1), 202 NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1200}}, []string{"ddl2"}, table1), 203 NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1400}}, []string{"ddl3"}, table1), 204 NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1600}}, []string{"ddl1"}, table2), 205 NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1800}}, []string{"ddl3"}, table2), 206 NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 2000}}, []string{"ddl2"}, table2), 207 } 208 ) 209 210 // 1st round sharding DDL sync 211 for i := 0; i < 4; i++ { 212 active, err = meta.AddItem(items[i]) 213 c.Assert(err, check.IsNil) 214 if i%3 == 0 { 215 c.Assert(active, check.IsTrue) 216 } else { 217 c.Assert(active, check.IsFalse) 218 } 219 } 220 // find synced in shrading group, and call ShardingMeta.ResolveShardingDDL 221 c.Assert(meta.ResolveShardingDDL(), check.IsFalse) 222 223 // 2nd round sharding DDL sync 224 for i := 0; i < 4; i++ { 225 if i%3 == 0 { 226 continue 227 } 228 active, err = meta.AddItem(items[i]) 229 c.Assert(err, check.IsNil) 230 if i%3 == 1 { 231 c.Assert(active, check.IsTrue) 232 } else { 233 c.Assert(active, check.IsFalse) 234 } 235 } 236 active, err = meta.AddItem(items[4]) 237 c.Assert(active, check.IsFalse) 238 c.Assert(err, check.ErrorMatches, "\\[.*\\], Message: detect inconsistent DDL sequence from source .*, right DDL sequence should be .*") 239 } 240 241 func (t *testShardMetaSuite) TestFlushLoadMeta(c *check.C) { 242 var ( 243 active bool 244 err error 245 filename = "mysql-bin.000001" 246 table1 = "table1" 247 table2 = "table2" 248 metaSchema = "dm_meta" 249 metaTable = "test_syncer_sharding_meta" 250 sourceID = "mysql-replica-01" 251 tableID = "`target_db`.`target_table`" 252 meta = NewShardingMeta(metaSchema, metaTable, false) 253 loadedMeta = NewShardingMeta(metaSchema, metaTable, false) 254 items = []*DDLItem{ 255 NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1000}}, []string{"ddl1"}, table1), 256 NewDDLItem(binlog.Location{Position: mysql.Position{Name: filename, Pos: 1200}}, []string{"ddl1"}, table2), 257 } 258 ) 259 for _, item := range items { 260 active, err = meta.AddItem(item) 261 c.Assert(err, check.IsNil) 262 c.Assert(active, check.IsTrue) 263 } 264 sqls, args := meta.FlushData(sourceID, tableID) 265 c.Assert(sqls, check.HasLen, 3) 266 c.Assert(args, check.HasLen, 3) 267 for _, arg := range args { 268 c.Assert(arg, check.HasLen, 8) 269 c.Assert(loadedMeta.RestoreFromData(arg[2].(string), arg[3].(int), arg[4].(bool), []byte(arg[5].(string)), mysql.MySQLFlavor), check.IsNil) 270 } 271 c.Assert(loadedMeta.activeIdx, check.Equals, meta.activeIdx) 272 c.Assert(loadedMeta.global.String(), check.Equals, meta.global.String()) 273 c.Assert(loadedMeta.tableName, check.Equals, meta.tableName) 274 c.Assert(len(loadedMeta.sources), check.Equals, len(meta.sources)) 275 for table, source := range loadedMeta.sources { 276 c.Assert(source.String(), check.Equals, meta.sources[table].String()) 277 } 278 }