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  }