github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/pkg/binlog/event/common_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 event 15 16 import ( 17 "fmt" 18 "os" 19 "path/filepath" 20 "testing" 21 22 gmysql "github.com/go-mysql-org/go-mysql/mysql" 23 "github.com/go-mysql-org/go-mysql/replication" 24 "github.com/pingcap/tiflow/dm/pkg/gtid" 25 "github.com/stretchr/testify/require" 26 ) 27 28 func TestGenCommonFileHeader(t *testing.T) { 29 t.Parallel() 30 var ( 31 flavor = gmysql.MySQLFlavor 32 serverID uint32 = 101 33 gSetStr = "3ccc475b-2343-11e7-be21-6c0b84d59f30:1-14,406a3f61-690d-11e7-87c5-6c92bf46f384:1-94321383,53bfca22-690d-11e7-8a62-18ded7a37b78:1-495,686e1ab6-c47e-11e7-a42c-6c92bf46f384:1-34981190,03fc0263-28c7-11e7-a653-6c0b84d59f30:1-7041423,05474d3c-28c7-11e7-8352-203db246dd3d:1-170,10b039fc-c843-11e7-8f6a-1866daf8d810:1-308290454" 34 gSet gmysql.GTIDSet 35 ) 36 gSet, err := gtid.ParserGTID(flavor, gSetStr) 37 require.Nil(t, err) 38 39 events, data, err := GenCommonFileHeader(flavor, serverID, gSet, true, 0) 40 require.Nil(t, err) 41 require.Equal(t, 2, len(events)) 42 require.Equal(t, replication.FORMAT_DESCRIPTION_EVENT, events[0].Header.EventType) 43 require.Equal(t, replication.PREVIOUS_GTIDS_EVENT, events[1].Header.EventType) 44 45 // write to file then parse it 46 dir := t.TempDir() 47 mysqlFilename := filepath.Join(dir, "mysql-bin-test.000001") 48 mysqlFile, err := os.Create(mysqlFilename) 49 require.Nil(t, err) 50 defer mysqlFile.Close() 51 52 _, err = mysqlFile.Write(data) 53 require.Nil(t, err) 54 55 count := 0 56 onEventFunc := func(e *replication.BinlogEvent) error { 57 count++ 58 if count > 2 { 59 t.Fatalf("too many binlog events got, current is %+v", e.Header) 60 } 61 require.Equal(t, events[count-1].Header, e.Header) 62 require.Equal(t, events[count-1].Event, e.Event) 63 require.Equal(t, events[count-1].RawData, e.RawData) 64 return nil 65 } 66 67 parser2 := replication.NewBinlogParser() 68 parser2.SetVerifyChecksum(true) 69 err = parser2.ParseFile(mysqlFilename, 0, onEventFunc) 70 require.Nil(t, err) 71 72 // MariaDB 73 flavor = gmysql.MariaDBFlavor 74 gSetStr = "1-2-12,2-2-3,3-3-8,3-4-9" 75 76 gSet, err = gtid.ParserGTID(flavor, gSetStr) 77 require.Nil(t, err) 78 79 events, data, err = GenCommonFileHeader(flavor, serverID, gSet, true, 0) 80 require.Nil(t, err) 81 require.Equal(t, 2, len(events)) 82 require.Equal(t, replication.FORMAT_DESCRIPTION_EVENT, events[0].Header.EventType) 83 require.Equal(t, replication.MARIADB_GTID_LIST_EVENT, events[1].Header.EventType) 84 85 mariadbFilename := filepath.Join(dir, "mariadb-bin-test.000001") 86 mariadbFile, err := os.Create(mariadbFilename) 87 require.Nil(t, err) 88 defer mariadbFile.Close() 89 90 _, err = mariadbFile.Write(data) 91 require.Nil(t, err) 92 93 count = 0 // reset to 0 94 err = parser2.ParseFile(mariadbFilename, 0, onEventFunc) 95 require.Nil(t, err) 96 } 97 98 func TestGenCommonGTIDEvent(t *testing.T) { 99 t.Parallel() 100 var ( 101 flavor = gmysql.MySQLFlavor 102 serverID uint32 = 101 103 gSet gmysql.GTIDSet 104 latestPos uint32 = 123 105 ) 106 107 // nil gSet, invalid 108 gtidEv, err := GenCommonGTIDEvent(flavor, serverID, latestPos, gSet, false, 0) 109 require.NotNil(t, err) 110 require.Nil(t, gtidEv) 111 112 // multi GTID in set, invalid 113 gSetStr := "03fc0263-28c7-11e7-a653-6c0b84d59f30:1-123,05474d3c-28c7-11e7-8352-203db246dd3d:1-456,10b039fc-c843-11e7-8f6a-1866daf8d810:1-789" 114 gSet, err = gtid.ParserGTID(flavor, gSetStr) 115 require.Nil(t, err) 116 gtidEv, err = GenCommonGTIDEvent(flavor, serverID, latestPos, gSet, false, 0) 117 require.NotNil(t, err) 118 require.Nil(t, gtidEv) 119 120 // multi intervals, invalid 121 gSetStr = "03fc0263-28c7-11e7-a653-6c0b84d59f30:1-123:200-456" 122 gSet, err = gtid.ParserGTID(flavor, gSetStr) 123 require.Nil(t, err) 124 gtidEv, err = GenCommonGTIDEvent(flavor, serverID, latestPos, gSet, false, 0) 125 require.NotNil(t, err) 126 require.Nil(t, gtidEv) 127 128 // interval > 1, invalid 129 gSetStr = "03fc0263-28c7-11e7-a653-6c0b84d59f30:1-123" 130 gSet, err = gtid.ParserGTID(flavor, gSetStr) 131 require.Nil(t, err) 132 gtidEv, err = GenCommonGTIDEvent(flavor, serverID, latestPos, gSet, false, 0) 133 require.NotNil(t, err) 134 require.Nil(t, gtidEv) 135 136 // valid 137 gSetStr = "03fc0263-28c7-11e7-a653-6c0b84d59f30:123" 138 gSet, err = gtid.ParserGTID(flavor, gSetStr) 139 require.Nil(t, err) 140 sid, err := ParseSID(gSetStr[:len(gSetStr)-4]) 141 require.Nil(t, err) 142 gtidEv, err = GenCommonGTIDEvent(flavor, serverID, latestPos, gSet, false, 0) 143 require.Nil(t, err) 144 require.NotNil(t, gtidEv) 145 require.Equal(t, replication.GTID_EVENT, gtidEv.Header.EventType) 146 147 // verify the body 148 gtidEvBody1, ok := gtidEv.Event.(*replication.GTIDEvent) 149 require.True(t, ok) 150 require.NotNil(t, gtidEvBody1) 151 require.Equal(t, sid.Bytes(), gtidEvBody1.SID) 152 require.Equal(t, int64(123), gtidEvBody1.GNO) 153 require.Equal(t, defaultGTIDFlags, gtidEvBody1.CommitFlag) 154 require.Equal(t, defaultLastCommitted, gtidEvBody1.LastCommitted) 155 require.Equal(t, defaultSequenceNumber, gtidEvBody1.SequenceNumber) 156 157 // change flavor to MariaDB 158 flavor = gmysql.MariaDBFlavor 159 160 // GTID mismatch with flavor 161 gtidEv, err = GenCommonGTIDEvent(flavor, serverID, latestPos, gSet, false, 0) 162 require.NotNil(t, err) 163 require.Nil(t, gtidEv) 164 165 // multi GTID in set, invalid 166 gSetStr = "1-2-3,4-5-6" 167 gSet, err = gtid.ParserGTID(flavor, gSetStr) 168 require.Nil(t, err) 169 gtidEv, err = GenCommonGTIDEvent(flavor, serverID, latestPos, gSet, false, 0) 170 require.NotNil(t, err) 171 require.Nil(t, gtidEv) 172 173 // server_id mismatch, invalid 174 gSetStr = "1-2-3" 175 gSet, err = gtid.ParserGTID(flavor, gSetStr) 176 require.Nil(t, err) 177 gtidEv, err = GenCommonGTIDEvent(flavor, serverID, latestPos, gSet, false, 0) 178 require.NotNil(t, err) 179 require.Nil(t, gtidEv) 180 181 // valid 182 gSetStr = fmt.Sprintf("1-%d-3", serverID) 183 gSet, err = gtid.ParserGTID(flavor, gSetStr) 184 require.Nil(t, err) 185 gtidEv, err = GenCommonGTIDEvent(flavor, serverID, latestPos, gSet, false, 0) 186 require.Nil(t, err) 187 require.NotNil(t, gtidEv) 188 require.Equal(t, replication.MARIADB_GTID_EVENT, gtidEv.Header.EventType) 189 190 // verify the body, we 191 gtidEvBody2, ok := gtidEv.Event.(*replication.MariadbGTIDEvent) 192 require.True(t, ok) 193 require.Equal(t, uint32(1), gtidEvBody2.GTID.DomainID) 194 require.Equal(t, serverID, gtidEvBody2.GTID.ServerID) 195 require.Equal(t, uint64(3), gtidEvBody2.GTID.SequenceNumber) 196 } 197 198 func TestGTIDIncrease(t *testing.T) { 199 t.Parallel() 200 var ( 201 flavor = gmysql.MySQLFlavor 202 gSetStr = "03fc0263-28c7-11e7-a653-6c0b84d59f30:123" 203 gSetIn gmysql.GTIDSet 204 gSetOut gmysql.GTIDSet 205 ) 206 207 // increase for MySQL 208 gSetIn, err := gtid.ParserGTID(flavor, gSetStr) 209 require.Nil(t, err) 210 gSetOut, err = GTIDIncrease(flavor, gSetIn) 211 require.Nil(t, err) 212 require.NotNil(t, gSetOut) 213 require.Equal(t, "03fc0263-28c7-11e7-a653-6c0b84d59f30:124", gSetOut.String()) 214 215 // increase for MariaDB 216 flavor = gmysql.MariaDBFlavor 217 gSetStr = "1-2-3" 218 gSetIn, err = gtid.ParserGTID(flavor, gSetStr) 219 require.Nil(t, err) 220 gSetOut, err = GTIDIncrease(flavor, gSetIn) 221 require.Nil(t, err) 222 require.NotNil(t, gSetOut) 223 require.Equal(t, "1-2-4", gSetOut.String()) 224 }