github.com/pingcap/ticdc@v0.0.0-20220526033649-485a10ef2652/cdc/model/owner_test.go (about) 1 // Copyright 2020 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 model 15 16 import ( 17 "math" 18 "testing" 19 20 "github.com/pingcap/check" 21 "github.com/pingcap/ticdc/pkg/util/testleak" 22 ) 23 24 func TestSuite(t *testing.T) { check.TestingT(t) } 25 26 type ownerCommonSuite struct{} 27 28 var _ = check.Suite(&ownerCommonSuite{}) 29 30 func (s *ownerCommonSuite) TestAdminJobType(c *check.C) { 31 defer testleak.AfterTest(c)() 32 names := map[AdminJobType]string{ 33 AdminNone: "noop", 34 AdminStop: "stop changefeed", 35 AdminResume: "resume changefeed", 36 AdminRemove: "remove changefeed", 37 AdminFinish: "finish changefeed", 38 AdminJobType(100): "unknown", 39 } 40 for job, name := range names { 41 c.Assert(job.String(), check.Equals, name) 42 } 43 44 isStopped := map[AdminJobType]bool{ 45 AdminNone: false, 46 AdminStop: true, 47 AdminResume: false, 48 AdminRemove: true, 49 AdminFinish: true, 50 } 51 for job, stopped := range isStopped { 52 c.Assert(job.IsStopState(), check.Equals, stopped) 53 } 54 } 55 56 func (s *ownerCommonSuite) TestDDLStateString(c *check.C) { 57 defer testleak.AfterTest(c)() 58 names := map[ChangeFeedDDLState]string{ 59 ChangeFeedSyncDML: "SyncDML", 60 ChangeFeedWaitToExecDDL: "WaitToExecDDL", 61 ChangeFeedExecDDL: "ExecDDL", 62 ChangeFeedDDLExecuteFailed: "DDLExecuteFailed", 63 ChangeFeedDDLState(100): "Unknown", 64 } 65 for state, name := range names { 66 c.Assert(state.String(), check.Equals, name) 67 } 68 } 69 70 func (s *ownerCommonSuite) TestTaskPositionMarshal(c *check.C) { 71 defer testleak.AfterTest(c)() 72 pos := &TaskPosition{ 73 ResolvedTs: 420875942036766723, 74 CheckPointTs: 420875940070686721, 75 } 76 expected := `{"checkpoint-ts":420875940070686721,"resolved-ts":420875942036766723,"count":0,"error":null}` 77 78 data, err := pos.Marshal() 79 c.Assert(err, check.IsNil) 80 c.Assert(data, check.DeepEquals, expected) 81 c.Assert(pos.String(), check.Equals, expected) 82 83 newPos := &TaskPosition{} 84 err = newPos.Unmarshal([]byte(data)) 85 c.Assert(err, check.IsNil) 86 c.Assert(newPos, check.DeepEquals, pos) 87 } 88 89 func (s *ownerCommonSuite) TestChangeFeedStatusMarshal(c *check.C) { 90 defer testleak.AfterTest(c)() 91 status := &ChangeFeedStatus{ 92 ResolvedTs: 420875942036766723, 93 CheckpointTs: 420875940070686721, 94 } 95 expected := `{"resolved-ts":420875942036766723,"checkpoint-ts":420875940070686721,"admin-job-type":0}` 96 97 data, err := status.Marshal() 98 c.Assert(err, check.IsNil) 99 c.Assert(data, check.DeepEquals, expected) 100 101 newStatus := &ChangeFeedStatus{} 102 err = newStatus.Unmarshal([]byte(data)) 103 c.Assert(err, check.IsNil) 104 c.Assert(newStatus, check.DeepEquals, status) 105 } 106 107 func (s *ownerCommonSuite) TestTableOperationState(c *check.C) { 108 defer testleak.AfterTest(c)() 109 processedMap := map[uint64]bool{ 110 OperDispatched: false, 111 OperProcessed: true, 112 OperFinished: true, 113 } 114 appliedMap := map[uint64]bool{ 115 OperDispatched: false, 116 OperProcessed: false, 117 OperFinished: true, 118 } 119 o := &TableOperation{} 120 121 for status, processed := range processedMap { 122 o.Status = status 123 c.Assert(o.TableProcessed(), check.Equals, processed) 124 } 125 for status, applied := range appliedMap { 126 o.Status = status 127 c.Assert(o.TableApplied(), check.Equals, applied) 128 } 129 130 // test clone nil operation. no-nil clone will be tested in `TestShouldBeDeepCopy` 131 var nilTableOper *TableOperation 132 c.Assert(nilTableOper.Clone(), check.IsNil) 133 } 134 135 func (s *ownerCommonSuite) TestTaskWorkloadMarshal(c *check.C) { 136 defer testleak.AfterTest(c)() 137 workload := &TaskWorkload{ 138 12: WorkloadInfo{Workload: uint64(1)}, 139 15: WorkloadInfo{Workload: uint64(3)}, 140 } 141 expected := `{"12":{"workload":1},"15":{"workload":3}}` 142 143 data, err := workload.Marshal() 144 c.Assert(err, check.IsNil) 145 c.Assert(data, check.Equals, expected) 146 147 newWorkload := &TaskWorkload{} 148 err = newWorkload.Unmarshal([]byte(data)) 149 c.Assert(err, check.IsNil) 150 c.Assert(newWorkload, check.DeepEquals, workload) 151 152 workload = nil 153 data, err = workload.Marshal() 154 c.Assert(err, check.IsNil) 155 c.Assert(data, check.Equals, "{}") 156 } 157 158 type taskStatusSuite struct{} 159 160 var _ = check.Suite(&taskStatusSuite{}) 161 162 func (s *taskStatusSuite) TestShouldBeDeepCopy(c *check.C) { 163 defer testleak.AfterTest(c)() 164 info := TaskStatus{ 165 166 Tables: map[TableID]*TableReplicaInfo{ 167 1: {StartTs: 100}, 168 2: {StartTs: 100}, 169 3: {StartTs: 100}, 170 4: {StartTs: 100}, 171 }, 172 Operation: map[TableID]*TableOperation{ 173 5: { 174 Delete: true, BoundaryTs: 6, Done: true, 175 }, 176 6: { 177 Delete: false, BoundaryTs: 7, Done: false, 178 }, 179 }, 180 AdminJobType: AdminStop, 181 } 182 183 clone := info.Clone() 184 assertIsSnapshot := func() { 185 c.Assert(clone.Tables, check.DeepEquals, map[TableID]*TableReplicaInfo{ 186 1: {StartTs: 100}, 187 2: {StartTs: 100}, 188 3: {StartTs: 100}, 189 4: {StartTs: 100}, 190 }) 191 c.Assert(clone.Operation, check.DeepEquals, map[TableID]*TableOperation{ 192 5: { 193 Delete: true, BoundaryTs: 6, Done: true, 194 }, 195 6: { 196 Delete: false, BoundaryTs: 7, Done: false, 197 }, 198 }) 199 c.Assert(clone.AdminJobType, check.Equals, AdminStop) 200 } 201 202 assertIsSnapshot() 203 204 info.Tables[7] = &TableReplicaInfo{StartTs: 100} 205 info.Operation[7] = &TableOperation{Delete: true, BoundaryTs: 7, Done: true} 206 207 info.Operation[5].BoundaryTs = 8 208 info.Tables[1].StartTs = 200 209 210 assertIsSnapshot() 211 } 212 213 func (s *taskStatusSuite) TestProcSnapshot(c *check.C) { 214 defer testleak.AfterTest(c)() 215 info := TaskStatus{ 216 Tables: map[TableID]*TableReplicaInfo{ 217 10: {StartTs: 100}, 218 }, 219 } 220 cfID := "changefeed-1" 221 captureID := "capture-1" 222 snap := info.Snapshot(cfID, captureID, 200) 223 c.Assert(snap.CfID, check.Equals, cfID) 224 c.Assert(snap.CaptureID, check.Equals, captureID) 225 c.Assert(snap.Tables, check.HasLen, 1) 226 c.Assert(snap.Tables[10], check.DeepEquals, &TableReplicaInfo{StartTs: 200}) 227 } 228 229 func (s *taskStatusSuite) TestTaskStatusMarshal(c *check.C) { 230 defer testleak.AfterTest(c)() 231 status := &TaskStatus{ 232 Tables: map[TableID]*TableReplicaInfo{ 233 1: {StartTs: 420875942036766723}, 234 }, 235 } 236 expected := `{"tables":{"1":{"start-ts":420875942036766723,"mark-table-id":0}},"operation":null,"admin-job-type":0}` 237 238 data, err := status.Marshal() 239 c.Assert(err, check.IsNil) 240 c.Assert(data, check.DeepEquals, expected) 241 c.Assert(status.String(), check.Equals, expected) 242 243 newStatus := &TaskStatus{} 244 err = newStatus.Unmarshal([]byte(data)) 245 c.Assert(err, check.IsNil) 246 c.Assert(newStatus, check.DeepEquals, status) 247 } 248 249 func (s *taskStatusSuite) TestAddTable(c *check.C) { 250 defer testleak.AfterTest(c)() 251 ts := uint64(420875942036766723) 252 expected := &TaskStatus{ 253 Tables: map[TableID]*TableReplicaInfo{ 254 1: {StartTs: ts}, 255 }, 256 Operation: map[TableID]*TableOperation{ 257 1: { 258 BoundaryTs: ts, 259 Status: OperDispatched, 260 }, 261 }, 262 } 263 status := &TaskStatus{} 264 status.AddTable(1, &TableReplicaInfo{StartTs: ts}, ts) 265 c.Assert(status, check.DeepEquals, expected) 266 267 // add existing table does nothing 268 status.AddTable(1, &TableReplicaInfo{StartTs: 1}, 1) 269 c.Assert(status, check.DeepEquals, expected) 270 } 271 272 func (s *taskStatusSuite) TestTaskStatusApplyState(c *check.C) { 273 defer testleak.AfterTest(c)() 274 ts1 := uint64(420875042036766723) 275 ts2 := uint64(420876783269969921) 276 status := &TaskStatus{} 277 status.AddTable(1, &TableReplicaInfo{StartTs: ts1}, ts1) 278 status.AddTable(2, &TableReplicaInfo{StartTs: ts2}, ts2) 279 c.Assert(status.SomeOperationsUnapplied(), check.IsTrue) 280 c.Assert(status.AppliedTs(), check.Equals, ts1) 281 282 status.Operation[1].Status = OperFinished 283 status.Operation[2].Status = OperFinished 284 c.Assert(status.SomeOperationsUnapplied(), check.IsFalse) 285 c.Assert(status.AppliedTs(), check.Equals, uint64(math.MaxUint64)) 286 } 287 288 type removeTableSuite struct{} 289 290 var _ = check.Suite(&removeTableSuite{}) 291 292 func (s *removeTableSuite) TestMoveTable(c *check.C) { 293 defer testleak.AfterTest(c)() 294 info := TaskStatus{ 295 Tables: map[TableID]*TableReplicaInfo{ 296 1: {StartTs: 100}, 297 2: {StartTs: 200}, 298 }, 299 } 300 301 replicaInfo, found := info.RemoveTable(2, 300, true) 302 c.Assert(found, check.IsTrue) 303 c.Assert(replicaInfo, check.DeepEquals, &TableReplicaInfo{StartTs: 200}) 304 c.Assert(info.Tables, check.HasKey, int64(1)) 305 c.Assert(info.Tables, check.Not(check.HasKey), int64(2)) 306 expectedFlag := uint64(1) // OperFlagMoveTable 307 c.Assert(info.Operation, check.DeepEquals, map[int64]*TableOperation{ 308 2: { 309 Delete: true, 310 Flag: expectedFlag, 311 BoundaryTs: 300, 312 Status: OperDispatched, 313 }, 314 }) 315 } 316 317 func (s *removeTableSuite) TestShouldReturnRemovedTable(c *check.C) { 318 defer testleak.AfterTest(c)() 319 info := TaskStatus{ 320 Tables: map[TableID]*TableReplicaInfo{ 321 1: {StartTs: 100}, 322 2: {StartTs: 200}, 323 3: {StartTs: 300}, 324 4: {StartTs: 400}, 325 }, 326 } 327 328 replicaInfo, found := info.RemoveTable(2, 666, false) 329 c.Assert(found, check.IsTrue) 330 c.Assert(replicaInfo, check.DeepEquals, &TableReplicaInfo{StartTs: 200}) 331 } 332 333 func (s *removeTableSuite) TestShouldHandleTableNotFound(c *check.C) { 334 defer testleak.AfterTest(c)() 335 info := TaskStatus{} 336 _, found := info.RemoveTable(404, 666, false) 337 c.Assert(found, check.IsFalse) 338 339 info = TaskStatus{ 340 Tables: map[TableID]*TableReplicaInfo{ 341 1: {StartTs: 100}, 342 }, 343 } 344 _, found = info.RemoveTable(404, 666, false) 345 c.Assert(found, check.IsFalse) 346 }