github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/ctl/master/query_status_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 master
    15  
    16  import (
    17  	"sort"
    18  	"testing"
    19  
    20  	"github.com/pingcap/check"
    21  	"github.com/pingcap/tiflow/dm/pb"
    22  )
    23  
    24  func TestCtlMaster(t *testing.T) {
    25  	check.TestingT(t)
    26  }
    27  
    28  type testCtlMaster struct{}
    29  
    30  var _ = check.Suite(&testCtlMaster{})
    31  
    32  func generateAndCheckTaskResult(c *check.C, resp *pb.QueryStatusListResponse, expectedResult []*taskInfo) {
    33  	result, hasFalseResult := wrapTaskResult(resp)
    34  	c.Assert(hasFalseResult, check.IsFalse)
    35  	c.Assert(result.Result, check.IsTrue)
    36  	c.Assert(result.Tasks, check.HasLen, 1)
    37  	sort.Strings(result.Tasks[0].Sources)
    38  	c.Assert(result.Tasks, check.DeepEquals, expectedResult)
    39  }
    40  
    41  func subTestSameSubTaskStatus(c *check.C, resp *pb.QueryStatusListResponse, expectedResult []*taskInfo, stage pb.Stage) {
    42  	for i := range resp.Sources {
    43  		resp.Sources[i].SubTaskStatus[0].Stage = stage
    44  	}
    45  	expectedResult[0].TaskStatus = stage.String()
    46  	generateAndCheckTaskResult(c, resp, expectedResult)
    47  }
    48  
    49  func (t *testCtlMaster) TestWrapTaskResult(c *check.C) {
    50  	resp := new(pb.QueryStatusListResponse)
    51  	resp.Result = true
    52  
    53  	// Should return error when some error occurs in subtask
    54  	resp.Sources = []*pb.QueryStatusResponse{
    55  		{
    56  			Result:       true,
    57  			SourceStatus: &pb.SourceStatus{Source: "mysql-replica-01"},
    58  			SubTaskStatus: []*pb.SubTaskStatus{{
    59  				Name:  "test",
    60  				Stage: pb.Stage_Running,
    61  			}},
    62  		},
    63  		{
    64  			Result:       true,
    65  			SourceStatus: &pb.SourceStatus{Source: "mysql-replica-02"},
    66  			SubTaskStatus: []*pb.SubTaskStatus{{
    67  				Name:  "test",
    68  				Stage: pb.Stage_Running,
    69  			}},
    70  		},
    71  		{
    72  			Result:       true,
    73  			SourceStatus: &pb.SourceStatus{Source: "mysql-replica-03"},
    74  			SubTaskStatus: []*pb.SubTaskStatus{{
    75  				Name:  "test",
    76  				Stage: pb.Stage_Paused,
    77  				Result: &pb.ProcessResult{
    78  					Errors: []*pb.ProcessError{{}},
    79  				},
    80  			}},
    81  		},
    82  	}
    83  	extraInfo := ". Please run `query-status test` to get more details."
    84  	expectedResult := []*taskInfo{{
    85  		TaskName:   "test",
    86  		TaskStatus: stageError + " - Some error occurred in subtask" + extraInfo,
    87  		Sources:    []string{"mysql-replica-01", "mysql-replica-02", "mysql-replica-03"},
    88  	}}
    89  	generateAndCheckTaskResult(c, resp, expectedResult)
    90  	// Should return error when subtask unit is "Sync" while relay status is not running
    91  	resp.Sources[2].SubTaskStatus[0].Result = nil
    92  	resp.Sources[0].SubTaskStatus[0].Unit = pb.UnitType_Sync
    93  	// relay status is Error
    94  	resp.Sources[0].SourceStatus.RelayStatus = &pb.RelayStatus{
    95  		Stage: pb.Stage_Paused,
    96  		Result: &pb.ProcessResult{
    97  			Errors: []*pb.ProcessError{{}},
    98  		},
    99  	}
   100  	expectedResult[0].TaskStatus = stageError + " - Relay status is " + stageError + extraInfo
   101  	generateAndCheckTaskResult(c, resp, expectedResult)
   102  	// relay status is Paused
   103  	resp.Sources[0].SourceStatus.RelayStatus = &pb.RelayStatus{Stage: pb.Stage_Paused}
   104  	expectedResult[0].TaskStatus = stageError + " - Relay status is " + pb.Stage_Paused.String() + extraInfo
   105  	generateAndCheckTaskResult(c, resp, expectedResult)
   106  	// relay status is Stopped
   107  	resp.Sources[0].SourceStatus.RelayStatus = &pb.RelayStatus{Stage: pb.Stage_Stopped}
   108  	expectedResult[0].TaskStatus = stageError + " - Relay status is " + pb.Stage_Stopped.String() + extraInfo
   109  	generateAndCheckTaskResult(c, resp, expectedResult)
   110  
   111  	// one subtask is paused and no error occurs, should return paused
   112  	resp.Sources[2].SubTaskStatus[0].Result = nil
   113  	resp.Sources[0].SubTaskStatus[0].Unit = 0
   114  	resp.Sources[0].SourceStatus.RelayStatus = nil
   115  	expectedResult[0].TaskStatus = pb.Stage_Paused.String()
   116  	generateAndCheckTaskResult(c, resp, expectedResult)
   117  	// All subtasks are Finished/Stopped/.../New
   118  	stageArray := []pb.Stage{pb.Stage_Finished, pb.Stage_Stopped, pb.Stage_Paused, pb.Stage_Running, pb.Stage_New}
   119  	for _, stage := range stageArray {
   120  		subTestSameSubTaskStatus(c, resp, expectedResult, stage)
   121  	}
   122  	// All subtasks are New except the last one(which is Finished)
   123  	resp.Sources[2].SubTaskStatus[0].Stage = pb.Stage_Finished
   124  	expectedResult[0].TaskStatus = pb.Stage_Running.String()
   125  	generateAndCheckTaskResult(c, resp, expectedResult)
   126  
   127  	// test situation with two tasks
   128  	resp.Sources = append(resp.Sources, &pb.QueryStatusResponse{
   129  		Result:       true,
   130  		SourceStatus: &pb.SourceStatus{Source: "mysql-replica-04"},
   131  		SubTaskStatus: []*pb.SubTaskStatus{{
   132  			Name:  "test2",
   133  			Stage: pb.Stage_Paused,
   134  			Result: &pb.ProcessResult{
   135  				Errors: []*pb.ProcessError{{}},
   136  			},
   137  		}},
   138  	})
   139  	result, hasFalseResult := wrapTaskResult(resp)
   140  	c.Assert(hasFalseResult, check.IsFalse)
   141  	c.Assert(result.Tasks, check.HasLen, 2)
   142  	if result.Tasks[0].TaskName == "test2" {
   143  		result.Tasks[0], result.Tasks[1] = result.Tasks[1], result.Tasks[0]
   144  	}
   145  	sort.Strings(result.Tasks[0].Sources)
   146  	expectedResult = []*taskInfo{
   147  		{
   148  			TaskName:   "test",
   149  			TaskStatus: pb.Stage_Running.String(),
   150  			Sources:    []string{"mysql-replica-01", "mysql-replica-02", "mysql-replica-03"},
   151  		}, {
   152  			TaskName:   "test2",
   153  			TaskStatus: stageError + " - Some error occurred in subtask. Please run `query-status test2` to get more details.",
   154  			Sources:    []string{"mysql-replica-04"},
   155  		},
   156  	}
   157  	c.Assert(result.Tasks, check.DeepEquals, expectedResult)
   158  
   159  	resp.Result = false
   160  	_, hasFalseResult = wrapTaskResult(resp)
   161  	c.Assert(hasFalseResult, check.IsTrue)
   162  
   163  	resp.Result = true
   164  	resp.Sources[0].Result = false
   165  	_, hasFalseResult = wrapTaskResult(resp)
   166  	c.Assert(hasFalseResult, check.IsTrue)
   167  
   168  	resp.Sources[0].Result = true
   169  	_, hasFalseResult = wrapTaskResult(resp)
   170  	c.Assert(hasFalseResult, check.IsFalse)
   171  }