github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/pkg/dumpling/utils_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 dumpling
    15  
    16  import (
    17  	"context"
    18  	"os"
    19  	"path"
    20  	"strings"
    21  	"testing"
    22  
    23  	"github.com/go-mysql-org/go-mysql/mysql"
    24  	"github.com/pingcap/tidb/dumpling/export"
    25  	"github.com/pingcap/tiflow/dm/pkg/gtid"
    26  	"github.com/pingcap/tiflow/dm/pkg/log"
    27  	"github.com/pingcap/tiflow/dm/pkg/terror"
    28  	"github.com/stretchr/testify/require"
    29  )
    30  
    31  func TestParseMetaData(t *testing.T) {
    32  	t.Parallel()
    33  	f, err := os.CreateTemp("", "metadata")
    34  	require.NoError(t, err)
    35  	defer os.Remove(f.Name())
    36  	fdir := path.Dir(f.Name())
    37  	fname := path.Base(f.Name())
    38  
    39  	testCases := []struct {
    40  		source   string
    41  		pos      mysql.Position
    42  		gsetStr  string
    43  		loc2     bool
    44  		pos2     mysql.Position
    45  		gsetStr2 string
    46  	}{
    47  		{
    48  			`Started dump at: 2018-12-28 07:20:49
    49  SHOW MASTER STATUS:
    50          Log: bin.000001
    51          Pos: 2479
    52          GTID:97b5142f-e19c-11e8-808c-0242ac110005:1-13
    53  
    54  Finished dump at: 2018-12-28 07:20:51`,
    55  			mysql.Position{
    56  				Name: "bin.000001",
    57  				Pos:  2479,
    58  			},
    59  			"97b5142f-e19c-11e8-808c-0242ac110005:1-13",
    60  			false,
    61  			mysql.Position{},
    62  			"",
    63  		},
    64  		{
    65  			`Started dump at: 2018-12-27 19:51:22
    66  SHOW MASTER STATUS:
    67          Log: mysql-bin.000003
    68          Pos: 3295817
    69          GTID:
    70  
    71  SHOW SLAVE STATUS:
    72          Host: 10.128.27.98
    73          Log: mysql-bin.000003
    74          Pos: 329635
    75          GTID:
    76  
    77  Finished dump at: 2018-12-27 19:51:22`,
    78  			mysql.Position{
    79  				Name: "mysql-bin.000003",
    80  				Pos:  3295817,
    81  			},
    82  			"",
    83  			false,
    84  			mysql.Position{},
    85  			"",
    86  		},
    87  		{ // with empty line after multiple GTID sets
    88  			`Started dump at: 2020-05-21 18:14:49
    89  SHOW MASTER STATUS:
    90  	Log: mysql-bin.000003
    91  	Pos: 1274
    92  	GTID:5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,
    93  5b642cb6-9b43-11ea-8914-0242ac170003:1-7,
    94  97b5142f-e19c-11e8-808c-0242ac110005:1-13
    95  
    96  SHOW SLAVE STATUS:
    97  	Host: 192.168.100.100
    98  	Log: mysql-bin.000003
    99  	Pos: 700
   100  	GTID:5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,
   101  5b642cb6-9b43-11ea-8914-0242ac170003:1-7,
   102  97b5142f-e19c-11e8-808c-0242ac110005:1-13
   103  
   104  Finished dump at: 2020-05-21 18:14:49`,
   105  			mysql.Position{
   106  				Name: "mysql-bin.000003",
   107  				Pos:  1274,
   108  			},
   109  			"5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,5b642cb6-9b43-11ea-8914-0242ac170003:1-7,97b5142f-e19c-11e8-808c-0242ac110005:1-13",
   110  			false,
   111  			mysql.Position{},
   112  			"",
   113  		},
   114  		{ // without empty line after mutlple GTID sets
   115  			`Started dump at: 2020-05-21 18:02:33
   116  SHOW MASTER STATUS:
   117  		Log: mysql-bin.000003
   118  		Pos: 1274
   119  		 GTID:5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,
   120  5b642cb6-9b43-11ea-8914-0242ac170003:1-7,
   121  97b5142f-e19c-11e8-808c-0242ac110005:1-13
   122  Finished dump at: 2020-05-21 18:02:44`,
   123  			mysql.Position{
   124  				Name: "mysql-bin.000003",
   125  				Pos:  1274,
   126  			},
   127  			"5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,5b642cb6-9b43-11ea-8914-0242ac170003:1-7,97b5142f-e19c-11e8-808c-0242ac110005:1-13",
   128  			false,
   129  			mysql.Position{},
   130  			"",
   131  		},
   132  		{ // with empty line after multiple GTID sets
   133  			`Started dump at: 2020-05-21 18:14:49
   134  SHOW MASTER STATUS:
   135  	Log: mysql-bin.000003
   136  	Pos: 1274
   137  	GTID:5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,
   138  5b642cb6-9b43-11ea-8914-0242ac170003:1-7,
   139  97b5142f-e19c-11e8-808c-0242ac110005:1-13
   140  
   141  SHOW SLAVE STATUS:
   142  	Host: 192.168.100.100
   143  	Log: mysql-bin.000003
   144  	Pos: 700
   145  	GTID:5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,
   146  5b642cb6-9b43-11ea-8914-0242ac170003:1-7,
   147  97b5142f-e19c-11e8-808c-0242ac110005:1-13
   148  
   149  SHOW MASTER STATUS: /* AFTER CONNECTION POOL ESTABLISHED */
   150  	Log: mysql-bin.000003
   151  	Pos: 1280
   152  	GTID:5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,
   153  5b642cb6-9b43-11ea-8914-0242ac170003:1-7,
   154  97b5142f-e19c-11e8-808c-0242ac110005:1-14
   155  
   156  Finished dump at: 2020-05-21 18:14:49`,
   157  			mysql.Position{
   158  				Name: "mysql-bin.000003",
   159  				Pos:  1274,
   160  			},
   161  			"5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,5b642cb6-9b43-11ea-8914-0242ac170003:1-7,97b5142f-e19c-11e8-808c-0242ac110005:1-13",
   162  			true,
   163  			mysql.Position{
   164  				Name: "mysql-bin.000003",
   165  				Pos:  1280,
   166  			},
   167  			"5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,5b642cb6-9b43-11ea-8914-0242ac170003:1-7,97b5142f-e19c-11e8-808c-0242ac110005:1-14",
   168  		},
   169  		{ // with empty line after multiple GTID sets
   170  			`Started dump at: 2020-05-21 18:14:49
   171  SHOW MASTER STATUS:
   172  	Log: mysql-bin.000003
   173  	Pos: 1274
   174  	GTID:5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,
   175  5b642cb6-9b43-11ea-8914-0242ac170003:1-7,
   176  97b5142f-e19c-11e8-808c-0242ac110005:1-13
   177  
   178  SHOW SLAVE STATUS:
   179  	Host: 192.168.100.100
   180  	Log: mysql-bin.000003
   181  	Pos: 700
   182  	GTID:5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,
   183  5b642cb6-9b43-11ea-8914-0242ac170003:1-7,
   184  97b5142f-e19c-11e8-808c-0242ac110005:1-13
   185  
   186  SHOW MASTER STATUS: /* AFTER CONNECTION POOL ESTABLISHED */
   187  	Log: mysql-bin.000004
   188  	Pos: 4
   189  	GTID:5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,
   190  5b642cb6-9b43-11ea-8914-0242ac170003:1-9,
   191  97b5142f-e19c-11e8-808c-0242ac110005:1-13
   192  
   193  Finished dump at: 2020-05-21 18:14:49`,
   194  			mysql.Position{
   195  				Name: "mysql-bin.000003",
   196  				Pos:  1274,
   197  			},
   198  			"5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,5b642cb6-9b43-11ea-8914-0242ac170003:1-7,97b5142f-e19c-11e8-808c-0242ac110005:1-13",
   199  			true,
   200  			mysql.Position{
   201  				Name: "mysql-bin.000004",
   202  				Pos:  4,
   203  			},
   204  			"5b5a8e4e-9b43-11ea-900d-0242ac170002:1-10,5b642cb6-9b43-11ea-8914-0242ac170003:1-9,97b5142f-e19c-11e8-808c-0242ac110005:1-13",
   205  		},
   206  		{ // no GTID sets
   207  			`Started dump at: 2020-09-30 12:16:49
   208  SHOW MASTER STATUS:
   209  	Log: mysql-bin-changelog.000003
   210  	Pos: 12470000
   211  
   212  SHOW MASTER STATUS: /* AFTER CONNECTION POOL ESTABLISHED */
   213  	Log: mysql-bin-changelog.000003
   214  	Pos: 12470000
   215  
   216  Finished dump at: 2020-09-30 12:16:49
   217  `,
   218  			mysql.Position{
   219  				Name: "mysql-bin-changelog.000003",
   220  				Pos:  12470000,
   221  			},
   222  			"",
   223  			true,
   224  			mysql.Position{
   225  				Name: "mysql-bin-changelog.000003",
   226  				Pos:  12470000,
   227  			},
   228  			"",
   229  		},
   230  	}
   231  	ctx := context.Background()
   232  	for _, tc := range testCases {
   233  		err2 := os.WriteFile(f.Name(), []byte(tc.source), 0o644)
   234  		require.NoError(t, err2)
   235  		loc, loc2, err2 := ParseMetaData(ctx, fdir, fname, nil)
   236  		require.NoError(t, err2)
   237  		require.Equal(t, tc.pos, loc.Position)
   238  		gs, _ := gtid.ParserGTID("mysql", tc.gsetStr)
   239  		require.Equal(t, gs, loc.GetGTID())
   240  		if tc.loc2 {
   241  			require.Equal(t, tc.pos2, loc2.Position)
   242  			gs2, _ := gtid.ParserGTID("mysql", tc.gsetStr2)
   243  			require.Equal(t, gs2, loc2.GetGTID())
   244  		} else {
   245  			require.Nil(t, loc2)
   246  		}
   247  	}
   248  
   249  	noBinlogLoc := `Started dump at: 2020-12-02 17:13:56
   250  Finished dump at: 2020-12-02 17:13:56
   251  `
   252  	err = os.WriteFile(f.Name(), []byte(noBinlogLoc), 0o644)
   253  	require.NoError(t, err)
   254  	_, _, err = ParseMetaData(ctx, fdir, fname, nil)
   255  	require.True(t, terror.ErrMetadataNoBinlogLoc.Equal(err))
   256  }
   257  
   258  func TestParseArgs(t *testing.T) {
   259  	t.Parallel()
   260  	logger := log.L()
   261  
   262  	exportCfg := export.DefaultConfig()
   263  	extraArgs := `--statement-size=100 --where t>10 --threads 8 -F 50B`
   264  	err := ParseExtraArgs(&logger, exportCfg, strings.Fields(extraArgs))
   265  	require.NoError(t, err)
   266  	require.Equal(t, uint64(100), exportCfg.StatementSize)
   267  	require.Equal(t, "t>10", exportCfg.Where)
   268  	require.Equal(t, 8, exportCfg.Threads)
   269  	require.Equal(t, uint64(50), exportCfg.FileSize)
   270  
   271  	extraArgs = `--threads 16 --skip-tz-utc`
   272  	err = ParseExtraArgs(&logger, exportCfg, strings.Fields(extraArgs))
   273  	require.Error(t, err)
   274  	require.Equal(t, 16, exportCfg.Threads)
   275  	require.Equal(t, uint64(100), exportCfg.StatementSize)
   276  
   277  	// no `--tables-list` or `--filter` specified, match anything
   278  	require.True(t, exportCfg.TableFilter.MatchTable("foo", "bar"))
   279  	require.True(t, exportCfg.TableFilter.MatchTable("bar", "foo"))
   280  
   281  	// specify `--tables-list`.
   282  	extraArgs = `--threads 16 --tables-list=foo.bar`
   283  	err = ParseExtraArgs(&logger, exportCfg, strings.Fields(extraArgs))
   284  	require.NoError(t, err)
   285  	require.True(t, exportCfg.TableFilter.MatchTable("foo", "bar"))
   286  	require.False(t, exportCfg.TableFilter.MatchTable("bar", "foo"))
   287  
   288  	// specify `--tables-list` and `--filter`
   289  	extraArgs = `--threads 16 --tables-list=foo.bar --filter=*.foo`
   290  	err = ParseExtraArgs(&logger, exportCfg, strings.Fields(extraArgs))
   291  	require.Regexp(t, ".*--tables-list and --filter together.*", err)
   292  
   293  	// only specify `--filter`.
   294  	extraArgs = `--threads 16 --filter=*.foo`
   295  	err = ParseExtraArgs(&logger, exportCfg, strings.Fields(extraArgs))
   296  	require.NoError(t, err)
   297  	require.False(t, exportCfg.TableFilter.MatchTable("foo", "bar"))
   298  	require.True(t, exportCfg.TableFilter.MatchTable("bar", "foo"))
   299  
   300  	// compatibility for `--no-locks`
   301  	extraArgs = `--no-locks`
   302  	err = ParseExtraArgs(&logger, exportCfg, strings.Fields(extraArgs))
   303  	require.NoError(t, err)
   304  	require.Equal(t, "none", exportCfg.Consistency)
   305  
   306  	// compatibility for `--no-locks`
   307  	extraArgs = `--no-locks --consistency none`
   308  	err = ParseExtraArgs(&logger, exportCfg, strings.Fields(extraArgs))
   309  	require.NoError(t, err)
   310  	require.Equal(t, "none", exportCfg.Consistency)
   311  
   312  	extraArgs = `--consistency lock`
   313  	err = ParseExtraArgs(&logger, exportCfg, strings.Fields(extraArgs))
   314  	require.NoError(t, err)
   315  	require.Equal(t, "lock", exportCfg.Consistency)
   316  
   317  	// compatibility for `--no-locks`
   318  	extraArgs = `--no-locks --consistency lock`
   319  	err = ParseExtraArgs(&logger, exportCfg, strings.Fields(extraArgs))
   320  	require.Equal(t, "cannot both specify `--no-locks` and `--consistency` other than `none`", err.Error())
   321  }