github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/pkg/utils/filename_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 utils
    15  
    16  import (
    17  	"testing"
    18  
    19  	"github.com/stretchr/testify/require"
    20  )
    21  
    22  func TestFilenameCmp(t *testing.T) {
    23  	t.Parallel()
    24  
    25  	f1 := Filename{
    26  		BaseName: "mysql-bin",
    27  		Seq:      "000001",
    28  		SeqInt64: 1,
    29  	}
    30  	f2 := Filename{
    31  		BaseName: "mysql-bin",
    32  		Seq:      "000002",
    33  		SeqInt64: 2,
    34  	}
    35  	f3 := Filename{
    36  		BaseName: "mysql-bin",
    37  		Seq:      "000001", // == f1
    38  		SeqInt64: 1,
    39  	}
    40  	f4 := Filename{
    41  		BaseName: "bin-mysq", // diff BaseName
    42  		Seq:      "000001",
    43  		SeqInt64: 1,
    44  	}
    45  
    46  	require.True(t, f1.LessThan(f2))
    47  	require.False(t, f1.GreaterThanOrEqualTo(f2))
    48  	require.False(t, f1.GreaterThan(f2))
    49  
    50  	require.False(t, f2.LessThan(f1))
    51  	require.True(t, f2.GreaterThanOrEqualTo(f1))
    52  	require.True(t, f2.GreaterThan(f1))
    53  
    54  	require.False(t, f1.LessThan(f3))
    55  	require.True(t, f1.GreaterThanOrEqualTo(f3))
    56  	require.False(t, f1.GreaterThan(f3))
    57  
    58  	require.False(t, f1.LessThan(f4))
    59  	require.False(t, f1.GreaterThanOrEqualTo(f4))
    60  	require.False(t, f1.GreaterThan(f4))
    61  }
    62  
    63  func TestParseFilenameAndGetFilenameIndex(t *testing.T) {
    64  	t.Parallel()
    65  
    66  	cases := []struct {
    67  		filenameStr string
    68  		filename    Filename
    69  		index       int64
    70  		errMsgReg   string
    71  	}{
    72  		{
    73  			// valid
    74  			filenameStr: "mysql-bin.666666",
    75  			filename:    Filename{"mysql-bin", "666666", 666666},
    76  			index:       666666,
    77  		},
    78  		{
    79  			// valid
    80  			filenameStr: "mysql-bin.000888",
    81  			filename:    Filename{"mysql-bin", "000888", 888},
    82  			index:       888,
    83  		},
    84  		{
    85  			// empty filename
    86  			filenameStr: "",
    87  			errMsgReg:   ".*invalid binlog filename.*",
    88  		},
    89  		{
    90  			// negative seq number
    91  			filenameStr: "mysql-bin.-666666",
    92  			errMsgReg:   ".*invalid binlog filename.*",
    93  		},
    94  		{
    95  			// zero seq number
    96  			filenameStr: "mysql-bin.000000",
    97  			errMsgReg:   ".*invalid binlog filename.*",
    98  		},
    99  		{
   100  			// too many separators
   101  			filenameStr: "mysql.bin.666666",
   102  			errMsgReg:   ".*invalid binlog filename.*",
   103  		},
   104  		{
   105  			// too less separators
   106  			filenameStr: "mysql-bin",
   107  			errMsgReg:   ".*invalid binlog filename.*",
   108  		},
   109  		{
   110  			// invalid seq number
   111  			filenameStr: "mysql-bin.666abc",
   112  			errMsgReg:   ".*invalid binlog filename.*",
   113  		},
   114  		{
   115  			// invalid seq number
   116  			filenameStr: "mysql-bin.def666",
   117  			errMsgReg:   ".*invalid binlog filename.*",
   118  		},
   119  		{
   120  			// invalid seq number
   121  			filenameStr: "mysql.bin",
   122  			errMsgReg:   ".*invalid binlog filename.*",
   123  		},
   124  	}
   125  
   126  	for _, cs := range cases {
   127  		f, err := ParseFilename(cs.filenameStr)
   128  		if len(cs.errMsgReg) > 0 {
   129  			require.Regexp(t, cs.errMsgReg, err)
   130  		} else {
   131  			require.NoError(t, err)
   132  		}
   133  		require.Equal(t, cs.filename, f)
   134  
   135  		idx, err := GetFilenameIndex(cs.filenameStr)
   136  		if len(cs.errMsgReg) > 0 {
   137  			require.Regexp(t, cs.errMsgReg, err)
   138  		} else {
   139  			require.NoError(t, err)
   140  		}
   141  		require.Equal(t, cs.index, idx)
   142  	}
   143  }
   144  
   145  func TestVerifyFilename(t *testing.T) {
   146  	t.Parallel()
   147  
   148  	cases := []struct {
   149  		filename string
   150  		valid    bool
   151  	}{
   152  		{
   153  			// valid
   154  			filename: "mysql-bin.666666",
   155  			valid:    true,
   156  		},
   157  		{
   158  			// empty filename
   159  			filename: "",
   160  		},
   161  		{
   162  			// negative seq number
   163  			filename: "mysql-bin.-666666",
   164  		},
   165  		{
   166  			// zero seq number
   167  			filename: "mysql-bin.000000",
   168  		},
   169  		{
   170  			// too many separators
   171  			filename: "mysql.bin.666666",
   172  		},
   173  		{
   174  			// too less separators
   175  			filename: "mysql-bin",
   176  		},
   177  		{
   178  			// invalid seq number
   179  			filename: "mysql-bin.666abc",
   180  		},
   181  		{
   182  			// invalid seq number
   183  			filename: "mysql-bin.def666",
   184  		},
   185  	}
   186  
   187  	for _, cs := range cases {
   188  		require.Equal(t, cs.valid, VerifyFilename(cs.filename))
   189  	}
   190  }
   191  
   192  func TestConstructFilename(t *testing.T) {
   193  	t.Parallel()
   194  
   195  	cases := []struct {
   196  		baseName string
   197  		seq      string
   198  		filename string
   199  	}{
   200  		{
   201  			baseName: "mysql-bin",
   202  			seq:      "000666",
   203  			filename: "mysql-bin.000666",
   204  		},
   205  	}
   206  
   207  	for _, cs := range cases {
   208  		require.Equal(t, cs.filename, ConstructFilename(cs.baseName, cs.seq))
   209  	}
   210  }
   211  
   212  func TestConstructFilenameWithUUIDSuffix(t *testing.T) {
   213  	t.Parallel()
   214  
   215  	cases := []struct {
   216  		originalName   Filename
   217  		suffix         string
   218  		withSuffixName string
   219  	}{
   220  		{
   221  			originalName:   Filename{"mysql-bin", "000001", 1},
   222  			suffix:         "666666",
   223  			withSuffixName: "mysql-bin|666666.000001",
   224  		},
   225  	}
   226  
   227  	for _, cs := range cases {
   228  		require.Equal(t, cs.withSuffixName, ConstructFilenameWithUUIDSuffix(cs.originalName, cs.suffix))
   229  		baseName, uuidSuffix, seq, err := SplitFilenameWithUUIDSuffix(cs.withSuffixName)
   230  		require.NoError(t, err)
   231  		require.Equal(t, cs.originalName.BaseName, baseName)
   232  		require.Equal(t, cs.suffix, uuidSuffix)
   233  		require.Equal(t, cs.originalName.Seq, seq)
   234  	}
   235  
   236  	invalidFileName := []string{
   237  		"mysql-bin.000001",
   238  		"mysql-bin.000001.000001",
   239  		"mysql-bin|000001",
   240  		"mysql-bin|000001|000001",
   241  		"mysql-bin|000001.000002.000003",
   242  	}
   243  
   244  	for _, fileName := range invalidFileName {
   245  		_, _, _, err := SplitFilenameWithUUIDSuffix(fileName)
   246  		require.Regexp(t, ".*invalid binlog filename with uuid suffix.*", err)
   247  	}
   248  }
   249  
   250  func TestExtractRealName(t *testing.T) {
   251  	t.Parallel()
   252  
   253  	cases := map[string]string{
   254  		"mysql-bin.000001":        "mysql-bin.000001",
   255  		"mysql-bin.000001|":       "mysql-bin.000001|", // should not happen in real case, just for test
   256  		"mysql-bin|000001.000001": "mysql-bin.000001",
   257  	}
   258  	for k, expected := range cases {
   259  		require.Equal(t, expected, ExtractRealName(k))
   260  	}
   261  }