github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/relay/file_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 relay
    15  
    16  import (
    17  	"os"
    18  	"path/filepath"
    19  
    20  	. "github.com/pingcap/check"
    21  	"github.com/pingcap/errors"
    22  	"github.com/pingcap/tiflow/dm/pkg/terror"
    23  	"github.com/pingcap/tiflow/dm/pkg/utils"
    24  )
    25  
    26  var _ = Suite(&testFileSuite{})
    27  
    28  type testFileSuite struct{}
    29  
    30  func (t *testFileSuite) TestCollectBinlogFiles(c *C) {
    31  	var (
    32  		valid = []string{
    33  			"mysql-bin.000001",
    34  			"mysql-bin.000002",
    35  			"mysql-bin.000003",
    36  			"mysql-bin.000004",
    37  		}
    38  		invalid = []string{
    39  			"mysql-bin.invalid01",
    40  			"mysql-bin.invalid02",
    41  		}
    42  		meta = []string{
    43  			utils.MetaFilename,
    44  			utils.MetaFilename + ".tmp",
    45  		}
    46  	)
    47  
    48  	files, err := CollectAllBinlogFiles("")
    49  	c.Assert(err, NotNil)
    50  	c.Assert(files, IsNil)
    51  
    52  	dir := c.MkDir()
    53  
    54  	// create all valid binlog files
    55  	for _, fn := range valid {
    56  		err = os.WriteFile(filepath.Join(dir, fn), nil, 0o600)
    57  		c.Assert(err, IsNil)
    58  	}
    59  	files, err = CollectAllBinlogFiles(dir)
    60  	c.Assert(err, IsNil)
    61  	c.Assert(files, DeepEquals, valid)
    62  
    63  	// create some invalid binlog files
    64  	for _, fn := range invalid {
    65  		err = os.WriteFile(filepath.Join(dir, fn), nil, 0o600)
    66  		c.Assert(err, IsNil)
    67  	}
    68  	files, err = CollectAllBinlogFiles(dir)
    69  	c.Assert(err, IsNil)
    70  	c.Assert(files, DeepEquals, valid)
    71  
    72  	// create some invalid meta files
    73  	for _, fn := range meta {
    74  		err = os.WriteFile(filepath.Join(dir, fn), nil, 0o600)
    75  		c.Assert(err, IsNil)
    76  	}
    77  	files, err = CollectAllBinlogFiles(dir)
    78  	c.Assert(err, IsNil)
    79  	c.Assert(files, DeepEquals, valid)
    80  
    81  	// collect newer files, none
    82  	files, err = CollectBinlogFilesCmp(dir, valid[len(valid)-1], FileCmpBigger)
    83  	c.Assert(err, IsNil)
    84  	c.Assert(files, DeepEquals, []string{})
    85  
    86  	// collect newer files, some
    87  	files, err = CollectBinlogFilesCmp(dir, valid[0], FileCmpBigger)
    88  	c.Assert(err, IsNil)
    89  	c.Assert(files, DeepEquals, valid[1:])
    90  
    91  	// collect newer or equal files, all
    92  	files, err = CollectBinlogFilesCmp(dir, valid[0], FileCmpBiggerEqual)
    93  	c.Assert(err, IsNil)
    94  	c.Assert(files, DeepEquals, valid)
    95  
    96  	// collect newer or equal files, some
    97  	files, err = CollectBinlogFilesCmp(dir, valid[1], FileCmpBiggerEqual)
    98  	c.Assert(err, IsNil)
    99  	c.Assert(files, DeepEquals, valid[1:])
   100  
   101  	// collect older files, none
   102  	files, err = CollectBinlogFilesCmp(dir, valid[0], FileCmpLess)
   103  	c.Assert(err, IsNil)
   104  	c.Assert(files, DeepEquals, []string{})
   105  
   106  	// collect older files, some
   107  	files, err = CollectBinlogFilesCmp(dir, valid[len(valid)-1], FileCmpLess)
   108  	c.Assert(err, IsNil)
   109  	c.Assert(files, DeepEquals, valid[:len(valid)-1])
   110  }
   111  
   112  func (t *testFileSuite) TestCollectBinlogFilesCmp(c *C) {
   113  	var (
   114  		dir         string
   115  		baseFile    string
   116  		cmp         = FileCmpEqual
   117  		binlogFiles = []string{
   118  			"mysql-bin.000001",
   119  			"mysql-bin.000002",
   120  			"mysql-bin.000003",
   121  			"mysql-bin.000004",
   122  		}
   123  	)
   124  
   125  	// empty dir
   126  	files, err := CollectBinlogFilesCmp(dir, baseFile, cmp)
   127  	c.Assert(terror.ErrEmptyRelayDir.Equal(err), IsTrue)
   128  	c.Assert(files, IsNil)
   129  
   130  	// empty base filename, not found
   131  	dir = c.MkDir()
   132  	files, err = CollectBinlogFilesCmp(dir, baseFile, cmp)
   133  	c.Assert(errors.IsNotFound(err), IsTrue)
   134  	c.Assert(files, IsNil)
   135  
   136  	// base file not found
   137  	baseFile = utils.MetaFilename
   138  	files, err = CollectBinlogFilesCmp(dir, baseFile, cmp)
   139  	c.Assert(errors.IsNotFound(err), IsTrue)
   140  	c.Assert(files, IsNil)
   141  
   142  	// create a meta file
   143  	filename := filepath.Join(dir, utils.MetaFilename)
   144  	err = os.WriteFile(filename, nil, 0o600)
   145  	c.Assert(err, IsNil)
   146  
   147  	// invalid base filename, is a meta filename
   148  	files, err = CollectBinlogFilesCmp(dir, baseFile, cmp)
   149  	c.Assert(err, ErrorMatches, ".*invalid binlog filename.*")
   150  	c.Assert(files, IsNil)
   151  
   152  	// create some binlog files
   153  	for _, f := range binlogFiles {
   154  		filename = filepath.Join(dir, f)
   155  		err = os.WriteFile(filename, nil, 0o600)
   156  		c.Assert(err, IsNil)
   157  	}
   158  
   159  	// > base file
   160  	cmp = FileCmpBigger
   161  	var i int
   162  	for i, baseFile = range binlogFiles {
   163  		files, err = CollectBinlogFilesCmp(dir, baseFile, cmp)
   164  		c.Assert(err, IsNil)
   165  		c.Assert(files, DeepEquals, binlogFiles[i+1:])
   166  	}
   167  
   168  	// >= base file
   169  	cmp = FileCmpBiggerEqual
   170  	for i, baseFile = range binlogFiles {
   171  		files, err = CollectBinlogFilesCmp(dir, baseFile, cmp)
   172  		c.Assert(err, IsNil)
   173  		c.Assert(files, DeepEquals, binlogFiles[i:])
   174  	}
   175  
   176  	// < base file
   177  	cmp = FileCmpLess
   178  	for i, baseFile = range binlogFiles {
   179  		files, err = CollectBinlogFilesCmp(dir, baseFile, cmp)
   180  		c.Assert(err, IsNil)
   181  		c.Assert(files, DeepEquals, binlogFiles[:i])
   182  	}
   183  
   184  	// add a basename mismatch binlog file
   185  	filename = filepath.Join(dir, "bin-mysql.100000")
   186  	err = os.WriteFile(filename, nil, 0o600)
   187  	c.Assert(err, IsNil)
   188  
   189  	// test again, should ignore it
   190  	for i, baseFile = range binlogFiles {
   191  		files, err = CollectBinlogFilesCmp(dir, baseFile, cmp)
   192  		c.Assert(err, IsNil)
   193  		c.Assert(files, DeepEquals, binlogFiles[:i])
   194  	}
   195  
   196  	// other cmp not supported yet
   197  	cmps := []FileCmp{FileCmpLessEqual, FileCmpEqual}
   198  	for _, cmp = range cmps {
   199  		files, err = CollectBinlogFilesCmp(dir, baseFile, cmp)
   200  		c.Assert(err, ErrorMatches, ".*not supported.*")
   201  		c.Assert(files, IsNil)
   202  	}
   203  }
   204  
   205  func (t *testFileSuite) TestGetFirstBinlogName(c *C) {
   206  	var (
   207  		baseDir = c.MkDir()
   208  		uuid    = "b60868af-5a6f-11e9-9ea3-0242ac160006.000001"
   209  		subDir  = filepath.Join(baseDir, uuid)
   210  	)
   211  
   212  	// sub directory not exist
   213  	name, err := getFirstBinlogName(baseDir, uuid)
   214  	c.Assert(err, ErrorMatches, ".*(no such file or directory|The system cannot find the file specified).*")
   215  	c.Assert(name, Equals, "")
   216  
   217  	// empty directory
   218  	err = os.MkdirAll(subDir, 0o700)
   219  	c.Assert(err, IsNil)
   220  	name, err = getFirstBinlogName(baseDir, uuid)
   221  	c.Assert(err, ErrorMatches, ".*not found.*")
   222  	c.Assert(name, Equals, "")
   223  
   224  	// has file, but not a valid binlog file. Now the error message is binlog files not found
   225  	filename := "invalid.bin"
   226  	err = os.WriteFile(filepath.Join(subDir, filename), nil, 0o600)
   227  	c.Assert(err, IsNil)
   228  	_, err = getFirstBinlogName(baseDir, uuid)
   229  	c.Assert(err, ErrorMatches, ".*not found.*")
   230  	err = os.Remove(filepath.Join(subDir, filename))
   231  	c.Assert(err, IsNil)
   232  
   233  	// has a valid binlog file
   234  	filename = "z-mysql-bin.000002" // z prefix, make it become not the _first_ if possible.
   235  	err = os.WriteFile(filepath.Join(subDir, filename), nil, 0o600)
   236  	c.Assert(err, IsNil)
   237  	name, err = getFirstBinlogName(baseDir, uuid)
   238  	c.Assert(err, IsNil)
   239  	c.Assert(name, Equals, filename)
   240  
   241  	// has one more earlier binlog file
   242  	filename = "z-mysql-bin.000001"
   243  	err = os.WriteFile(filepath.Join(subDir, filename), nil, 0o600)
   244  	c.Assert(err, IsNil)
   245  	name, err = getFirstBinlogName(baseDir, uuid)
   246  	c.Assert(err, IsNil)
   247  	c.Assert(name, Equals, filename)
   248  
   249  	// has a meta file
   250  	err = os.WriteFile(filepath.Join(subDir, utils.MetaFilename), nil, 0o600)
   251  	c.Assert(err, IsNil)
   252  	name, err = getFirstBinlogName(baseDir, uuid)
   253  	c.Assert(err, IsNil)
   254  	c.Assert(name, Equals, filename)
   255  }
   256  
   257  func (t *testFileSuite) TestFileSizeUpdated(c *C) {
   258  	var (
   259  		filename   = "mysql-bin.000001"
   260  		filePath   = filepath.Join(c.MkDir(), filename)
   261  		data       = []byte("meaningless file content")
   262  		latestSize = int64(len(data))
   263  	)
   264  
   265  	// file not exists
   266  	cmp, err := fileSizeUpdated(filePath, latestSize)
   267  	c.Assert(err, ErrorMatches, ".*(no such file or directory|The system cannot find the file specified).*")
   268  	c.Assert(cmp, Equals, 0)
   269  
   270  	// create and write the file
   271  	err = os.WriteFile(filePath, data, 0o600)
   272  	c.Assert(err, IsNil)
   273  
   274  	// equal
   275  	cmp, err = fileSizeUpdated(filePath, latestSize)
   276  	c.Assert(err, IsNil)
   277  	c.Assert(cmp, Equals, 0)
   278  
   279  	// less than
   280  	cmp, err = fileSizeUpdated(filePath, latestSize+1)
   281  	c.Assert(err, IsNil)
   282  	c.Assert(cmp, Equals, -1)
   283  
   284  	// greater than
   285  	cmp, err = fileSizeUpdated(filePath, latestSize-1)
   286  	c.Assert(err, IsNil)
   287  	c.Assert(cmp, Equals, 1)
   288  }