github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/pkg/checker/lightning_test.go (about)

     1  // Copyright 2022 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 checker
    15  
    16  import (
    17  	"context"
    18  	"testing"
    19  
    20  	"github.com/pingcap/tidb/lightning/pkg/precheck"
    21  	"github.com/pingcap/tiflow/pkg/errors"
    22  	"github.com/stretchr/testify/require"
    23  )
    24  
    25  type mockPrecheckItem struct {
    26  	err  error
    27  	pass bool
    28  	msg  string
    29  }
    30  
    31  func (m mockPrecheckItem) Check(ctx context.Context) (*precheck.CheckResult, error) {
    32  	if m.err != nil {
    33  		return nil, m.err
    34  	}
    35  	return &precheck.CheckResult{
    36  		Passed:  m.pass,
    37  		Message: m.msg,
    38  	}, nil
    39  }
    40  
    41  func (m mockPrecheckItem) GetCheckItemID() precheck.CheckItemID {
    42  	return "mock"
    43  }
    44  
    45  // nolint:dupl
    46  func TestEmptyRegionChecker(t *testing.T) {
    47  	ctx := context.Background()
    48  	c := &LightningEmptyRegionChecker{inner: mockPrecheckItem{pass: true}}
    49  	result := c.Check(ctx)
    50  	require.Equal(t, StateSuccess, result.State)
    51  	require.Len(t, result.Errors, 0)
    52  	require.Equal(t, "", result.Extra)
    53  
    54  	c.inner = mockPrecheckItem{err: errors.New("mock error")}
    55  	result = c.Check(ctx)
    56  	require.Equal(t, StateFailure, result.State)
    57  	require.Equal(t, "", result.Extra)
    58  	require.Len(t, result.Errors, 1)
    59  	require.Equal(t, "mock error", result.Errors[0].ShortErr)
    60  	require.Equal(t, StateFailure, result.Errors[0].Severity)
    61  
    62  	// lightning prechecker returns fail
    63  	lightningMsg := "TiKV stores (1) contains more than 1000 empty regions respectively, which will greatly affect the import speed and success rate"
    64  	c.inner = mockPrecheckItem{msg: lightningMsg}
    65  	result = c.Check(ctx)
    66  	require.Equal(t, StateWarning, result.State)
    67  	require.Equal(t, "", result.Extra)
    68  	require.Len(t, result.Errors, 1)
    69  	require.Equal(t, lightningMsg, result.Errors[0].ShortErr)
    70  	require.Equal(t, StateWarning, result.Errors[0].Severity)
    71  
    72  	// lightning prechecker returns warning or success
    73  	lightningMsg = "Cluster doesn't have too many empty regions"
    74  	c.inner = mockPrecheckItem{msg: lightningMsg, pass: true}
    75  	result = c.Check(ctx)
    76  	require.Equal(t, StateSuccess, result.State)
    77  	require.Equal(t, "", result.Extra)
    78  	require.Len(t, result.Errors, 0)
    79  }
    80  
    81  // nolint:dupl
    82  func TestRegionUnbalanced(t *testing.T) {
    83  	ctx := context.Background()
    84  	c := &LightningRegionDistributionChecker{inner: mockPrecheckItem{pass: true}}
    85  	result := c.Check(ctx)
    86  	require.Equal(t, StateSuccess, result.State)
    87  	require.Len(t, result.Errors, 0)
    88  	require.Equal(t, "", result.Extra)
    89  
    90  	c.inner = mockPrecheckItem{err: errors.New("mock error")}
    91  	result = c.Check(ctx)
    92  	require.Equal(t, StateFailure, result.State)
    93  	require.Equal(t, "", result.Extra)
    94  	require.Len(t, result.Errors, 1)
    95  	require.Equal(t, "mock error", result.Errors[0].ShortErr)
    96  	require.Equal(t, StateFailure, result.Errors[0].Severity)
    97  
    98  	// lightning prechecker returns fail
    99  	lightningMsg := "Region distribution is unbalanced, the ratio of the regions count of the store(2) with least regions(500) to the store(1) with most regions(5000) is 0.1, but we expect it must not be less than 0.5"
   100  	c.inner = mockPrecheckItem{msg: lightningMsg}
   101  	result = c.Check(ctx)
   102  	require.Equal(t, StateWarning, result.State)
   103  	require.Equal(t, "", result.Extra)
   104  	require.Len(t, result.Errors, 1)
   105  	require.Equal(t, lightningMsg, result.Errors[0].ShortErr)
   106  	require.Equal(t, StateWarning, result.Errors[0].Severity)
   107  
   108  	// lightning prechecker returns warning or success
   109  	lightningMsg = "Cluster region distribution is balanced"
   110  	c.inner = mockPrecheckItem{msg: lightningMsg, pass: true}
   111  	result = c.Check(ctx)
   112  	require.Equal(t, StateSuccess, result.State)
   113  	require.Equal(t, "", result.Extra)
   114  	require.Len(t, result.Errors, 0)
   115  }
   116  
   117  func TestClusterVersion(t *testing.T) {
   118  	ctx := context.Background()
   119  	c := &LightningClusterVersionChecker{inner: mockPrecheckItem{pass: true}}
   120  	result := c.Check(ctx)
   121  	require.Equal(t, StateSuccess, result.State)
   122  	require.Len(t, result.Errors, 0)
   123  	require.Equal(t, "", result.Extra)
   124  
   125  	c.inner = mockPrecheckItem{err: errors.New("mock error")}
   126  	result = c.Check(ctx)
   127  	require.Equal(t, StateFailure, result.State)
   128  	require.Equal(t, "", result.Extra)
   129  	require.Len(t, result.Errors, 1)
   130  	require.Equal(t, "mock error", result.Errors[0].ShortErr)
   131  	require.Equal(t, StateFailure, result.Errors[0].Severity)
   132  
   133  	lightningMsg := "Cluster version check failed: TiNB version too old, required to be in [2.3.5, 3.0.0), found '2.1.0': [BR:Common:ErrVersionMismatch]version mismatch"
   134  	c.inner = mockPrecheckItem{msg: lightningMsg}
   135  	result = c.Check(ctx)
   136  	require.Equal(t, StateFailure, result.State)
   137  	require.Equal(t, "", result.Extra)
   138  	require.Len(t, result.Errors, 1)
   139  	require.Equal(t, lightningMsg, result.Errors[0].ShortErr)
   140  	require.Equal(t, StateFailure, result.Errors[0].Severity)
   141  }
   142  
   143  func TestTableEmpty(t *testing.T) {
   144  	ctx := context.Background()
   145  	c := &LightningTableEmptyChecker{inner: mockPrecheckItem{pass: true}}
   146  	result := c.Check(ctx)
   147  	require.Equal(t, StateSuccess, result.State)
   148  	require.Len(t, result.Errors, 0)
   149  	require.Equal(t, "", result.Extra)
   150  
   151  	c.inner = mockPrecheckItem{err: errors.New("mock error")}
   152  	result = c.Check(ctx)
   153  	require.Equal(t, StateFailure, result.State)
   154  	require.Equal(t, "", result.Extra)
   155  	require.Len(t, result.Errors, 1)
   156  	require.Equal(t, "mock error", result.Errors[0].ShortErr)
   157  	require.Equal(t, StateFailure, result.Errors[0].Severity)
   158  
   159  	lightningMsg := "table(s) [test.t1] are not empty"
   160  	c.inner = mockPrecheckItem{msg: lightningMsg}
   161  	result = c.Check(ctx)
   162  	require.Equal(t, StateFailure, result.State)
   163  	require.Equal(t, "", result.Extra)
   164  	require.Len(t, result.Errors, 1)
   165  	require.Equal(t, lightningMsg, result.Errors[0].ShortErr)
   166  	require.Equal(t, StateFailure, result.Errors[0].Severity)
   167  }