github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/shared/filestore/filesstore_test.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package filestore
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"io/ioutil"
    10  	"math/rand"
    11  	"os"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/stretchr/testify/require"
    16  	"github.com/stretchr/testify/suite"
    17  	"github.com/xtgo/uuid"
    18  
    19  	"github.com/masterhung0112/hk_server/v5/shared/mlog"
    20  )
    21  
    22  func randomString() string {
    23  	return uuid.NewRandom().String()
    24  }
    25  
    26  type FileBackendTestSuite struct {
    27  	suite.Suite
    28  
    29  	settings FileBackendSettings
    30  	backend  FileBackend
    31  }
    32  
    33  func TestLocalFileBackendTestSuite(t *testing.T) {
    34  	// Setup a global logger to catch tests logging outside of app context
    35  	// The global logger will be stomped by apps initializing but that's fine for testing. Ideally this won't happen.
    36  	mlog.InitGlobalLogger(mlog.NewLogger(&mlog.LoggerConfiguration{
    37  		EnableConsole: true,
    38  		ConsoleJson:   true,
    39  		ConsoleLevel:  "error",
    40  		EnableFile:    false,
    41  	}))
    42  
    43  	dir, err := ioutil.TempDir("", "")
    44  	require.NoError(t, err)
    45  	defer os.RemoveAll(dir)
    46  
    47  	suite.Run(t, &FileBackendTestSuite{
    48  		settings: FileBackendSettings{
    49  			DriverName: driverLocal,
    50  			Directory:  dir,
    51  		},
    52  	})
    53  }
    54  
    55  func TestS3FileBackendTestSuite(t *testing.T) {
    56  	runBackendTest(t, false)
    57  }
    58  
    59  func TestS3FileBackendTestSuiteWithEncryption(t *testing.T) {
    60  	runBackendTest(t, true)
    61  }
    62  
    63  func runBackendTest(t *testing.T, encrypt bool) {
    64  	s3Host := os.Getenv("CI_MINIO_HOST")
    65  	if s3Host == "" {
    66  		s3Host = "localhost"
    67  	}
    68  
    69  	s3Port := os.Getenv("CI_MINIO_PORT")
    70  	if s3Port == "" {
    71  		s3Port = "9000"
    72  	}
    73  
    74  	s3Endpoint := fmt.Sprintf("%s:%s", s3Host, s3Port)
    75  
    76  	suite.Run(t, &FileBackendTestSuite{
    77  		settings: FileBackendSettings{
    78  			DriverName:              driverS3,
    79  			AmazonS3AccessKeyId:     "minioaccesskey",
    80  			AmazonS3SecretAccessKey: "miniosecretkey",
    81  			AmazonS3Bucket:          "mattermost-test",
    82  			AmazonS3Region:          "",
    83  			AmazonS3Endpoint:        s3Endpoint,
    84  			AmazonS3PathPrefix:      "",
    85  			AmazonS3SSL:             false,
    86  			AmazonS3SSE:             encrypt,
    87  		},
    88  	})
    89  }
    90  
    91  func (s *FileBackendTestSuite) SetupTest() {
    92  	backend, err := NewFileBackend(s.settings)
    93  	require.NoError(s.T(), err)
    94  	s.backend = backend
    95  
    96  	// This is needed to create the bucket if it doesn't exist.
    97  	err = s.backend.TestConnection()
    98  	if _, ok := err.(*S3FileBackendNoBucketError); ok {
    99  		s3Backend := s.backend.(*S3FileBackend)
   100  		s.NoError(s3Backend.MakeBucket())
   101  	} else {
   102  		s.NoError(err)
   103  	}
   104  }
   105  
   106  func (s *FileBackendTestSuite) TestConnection() {
   107  	s.Nil(s.backend.TestConnection())
   108  }
   109  
   110  func (s *FileBackendTestSuite) TestReadWriteFile() {
   111  	b := []byte("test")
   112  	path := "tests/" + randomString()
   113  
   114  	written, err := s.backend.WriteFile(bytes.NewReader(b), path)
   115  	s.Nil(err)
   116  	s.EqualValues(len(b), written, "expected given number of bytes to have been written")
   117  	defer s.backend.RemoveFile(path)
   118  
   119  	read, err := s.backend.ReadFile(path)
   120  	s.Nil(err)
   121  
   122  	readString := string(read)
   123  	s.EqualValues(readString, "test")
   124  }
   125  
   126  func (s *FileBackendTestSuite) TestReadWriteFileImage() {
   127  	b := []byte("testimage")
   128  	path := "tests/" + randomString() + ".png"
   129  
   130  	written, err := s.backend.WriteFile(bytes.NewReader(b), path)
   131  	s.Nil(err)
   132  	s.EqualValues(len(b), written, "expected given number of bytes to have been written")
   133  	defer s.backend.RemoveFile(path)
   134  
   135  	read, err := s.backend.ReadFile(path)
   136  	s.Nil(err)
   137  
   138  	readString := string(read)
   139  	s.EqualValues(readString, "testimage")
   140  }
   141  
   142  func (s *FileBackendTestSuite) TestFileExists() {
   143  	b := []byte("testimage")
   144  	path := "tests/" + randomString() + ".png"
   145  
   146  	_, err := s.backend.WriteFile(bytes.NewReader(b), path)
   147  	s.Nil(err)
   148  	defer s.backend.RemoveFile(path)
   149  
   150  	res, err := s.backend.FileExists(path)
   151  	s.Nil(err)
   152  	s.True(res)
   153  
   154  	res, err = s.backend.FileExists("tests/idontexist.png")
   155  	s.Nil(err)
   156  	s.False(res)
   157  }
   158  
   159  func (s *FileBackendTestSuite) TestCopyFile() {
   160  	b := []byte("test")
   161  	path1 := "tests/" + randomString()
   162  	path2 := "tests/" + randomString()
   163  
   164  	written, err := s.backend.WriteFile(bytes.NewReader(b), path1)
   165  	s.Nil(err)
   166  	s.EqualValues(len(b), written, "expected given number of bytes to have been written")
   167  	defer s.backend.RemoveFile(path1)
   168  
   169  	err = s.backend.CopyFile(path1, path2)
   170  	s.Nil(err)
   171  	defer s.backend.RemoveFile(path2)
   172  
   173  	data1, err := s.backend.ReadFile(path1)
   174  	s.Nil(err)
   175  
   176  	data2, err := s.backend.ReadFile(path2)
   177  	s.Nil(err)
   178  
   179  	s.Equal(b, data1)
   180  	s.Equal(b, data2)
   181  }
   182  
   183  func (s *FileBackendTestSuite) TestCopyFileToDirectoryThatDoesntExist() {
   184  	b := []byte("test")
   185  	path1 := "tests/" + randomString()
   186  	path2 := "tests/newdirectory/" + randomString()
   187  
   188  	written, err := s.backend.WriteFile(bytes.NewReader(b), path1)
   189  	s.Nil(err)
   190  	s.EqualValues(len(b), written, "expected given number of bytes to have been written")
   191  	defer s.backend.RemoveFile(path1)
   192  
   193  	err = s.backend.CopyFile(path1, path2)
   194  	s.Nil(err)
   195  	defer s.backend.RemoveFile(path2)
   196  
   197  	_, err = s.backend.ReadFile(path1)
   198  	s.Nil(err)
   199  
   200  	_, err = s.backend.ReadFile(path2)
   201  	s.Nil(err)
   202  }
   203  
   204  func (s *FileBackendTestSuite) TestMoveFile() {
   205  	b := []byte("test")
   206  	path1 := "tests/" + randomString()
   207  	path2 := "tests/" + randomString()
   208  
   209  	written, err := s.backend.WriteFile(bytes.NewReader(b), path1)
   210  	s.Nil(err)
   211  	s.EqualValues(len(b), written, "expected given number of bytes to have been written")
   212  	defer s.backend.RemoveFile(path1)
   213  
   214  	s.Nil(s.backend.MoveFile(path1, path2))
   215  	defer s.backend.RemoveFile(path2)
   216  
   217  	_, err = s.backend.ReadFile(path1)
   218  	s.Error(err)
   219  
   220  	data, err := s.backend.ReadFile(path2)
   221  	s.Nil(err)
   222  
   223  	s.Equal(b, data)
   224  }
   225  
   226  func (s *FileBackendTestSuite) TestRemoveFile() {
   227  	b := []byte("test")
   228  	path := "tests/" + randomString()
   229  
   230  	written, err := s.backend.WriteFile(bytes.NewReader(b), path)
   231  	s.Nil(err)
   232  	s.EqualValues(len(b), written, "expected given number of bytes to have been written")
   233  	s.Nil(s.backend.RemoveFile(path))
   234  
   235  	_, err = s.backend.ReadFile(path)
   236  	s.Error(err)
   237  
   238  	written, err = s.backend.WriteFile(bytes.NewReader(b), "tests2/foo")
   239  	s.Nil(err)
   240  	s.EqualValues(len(b), written, "expected given number of bytes to have been written")
   241  
   242  	written, err = s.backend.WriteFile(bytes.NewReader(b), "tests2/bar")
   243  	s.Nil(err)
   244  	s.EqualValues(len(b), written, "expected given number of bytes to have been written")
   245  
   246  	written, err = s.backend.WriteFile(bytes.NewReader(b), "tests2/asdf")
   247  	s.Nil(err)
   248  	s.EqualValues(len(b), written, "expected given number of bytes to have been written")
   249  
   250  	s.Nil(s.backend.RemoveDirectory("tests2"))
   251  }
   252  
   253  func (s *FileBackendTestSuite) TestListDirectory() {
   254  	b := []byte("test")
   255  	path1 := "19700101/" + randomString()
   256  	path2 := "19800101/" + randomString()
   257  
   258  	paths, err := s.backend.ListDirectory("19700101")
   259  	s.Nil(err)
   260  	s.Len(paths, 0)
   261  
   262  	written, err := s.backend.WriteFile(bytes.NewReader(b), path1)
   263  	s.Nil(err)
   264  	s.EqualValues(len(b), written, "expected given number of bytes to have been written")
   265  
   266  	written, err = s.backend.WriteFile(bytes.NewReader(b), path2)
   267  	s.Nil(err)
   268  	s.EqualValues(len(b), written, "expected given number of bytes to have been written")
   269  
   270  	paths, err = s.backend.ListDirectory("19700101")
   271  	s.Nil(err)
   272  	s.Len(paths, 1)
   273  	s.Equal(path1, (paths)[0])
   274  
   275  	paths, err = s.backend.ListDirectory("19700101/")
   276  	s.Nil(err)
   277  	s.Len(paths, 1)
   278  	s.Equal(path1, (paths)[0])
   279  
   280  	paths, err = s.backend.ListDirectory("")
   281  	s.Nil(err)
   282  
   283  	found1 := false
   284  	found2 := false
   285  	for _, path := range paths {
   286  		if path == "19700101" {
   287  			found1 = true
   288  		} else if path == "19800101" {
   289  			found2 = true
   290  		}
   291  	}
   292  	s.True(found1)
   293  	s.True(found2)
   294  
   295  	s.backend.RemoveFile(path1)
   296  	s.backend.RemoveFile(path2)
   297  }
   298  
   299  func (s *FileBackendTestSuite) TestRemoveDirectory() {
   300  	b := []byte("test")
   301  
   302  	written, err := s.backend.WriteFile(bytes.NewReader(b), "tests2/foo")
   303  	s.Nil(err)
   304  	s.EqualValues(len(b), written, "expected given number of bytes to have been written")
   305  
   306  	written, err = s.backend.WriteFile(bytes.NewReader(b), "tests2/bar")
   307  	s.Nil(err)
   308  	s.EqualValues(len(b), written, "expected given number of bytes to have been written")
   309  
   310  	written, err = s.backend.WriteFile(bytes.NewReader(b), "tests2/aaa")
   311  	s.Nil(err)
   312  	s.EqualValues(len(b), written, "expected given number of bytes to have been written")
   313  
   314  	s.Nil(s.backend.RemoveDirectory("tests2"))
   315  
   316  	_, err = s.backend.ReadFile("tests2/foo")
   317  	s.Error(err)
   318  	_, err = s.backend.ReadFile("tests2/bar")
   319  	s.Error(err)
   320  	_, err = s.backend.ReadFile("tests2/asdf")
   321  	s.Error(err)
   322  }
   323  
   324  func (s *FileBackendTestSuite) TestAppendFile() {
   325  	s.Run("should fail if target file is missing", func() {
   326  		path := "tests/" + randomString()
   327  		b := make([]byte, 1024)
   328  		written, err := s.backend.AppendFile(bytes.NewReader(b), path)
   329  		s.Error(err)
   330  		s.Zero(written)
   331  	})
   332  
   333  	s.Run("should correctly append the data", func() {
   334  		// First part needs to be at least 5MB for the S3 implementation to work.
   335  		size := 5 * 1024 * 1024
   336  		b := make([]byte, size)
   337  		for i := range b {
   338  			b[i] = 'A'
   339  		}
   340  		path := "tests/" + randomString()
   341  
   342  		written, err := s.backend.WriteFile(bytes.NewReader(b), path)
   343  		s.Nil(err)
   344  		s.EqualValues(len(b), written)
   345  		defer s.backend.RemoveFile(path)
   346  
   347  		b2 := make([]byte, 1024)
   348  		for i := range b2 {
   349  			b2[i] = 'B'
   350  		}
   351  
   352  		written, err = s.backend.AppendFile(bytes.NewReader(b2), path)
   353  		s.Nil(err)
   354  		s.EqualValues(int64(len(b2)), written)
   355  
   356  		read, err := s.backend.ReadFile(path)
   357  		s.Nil(err)
   358  		s.EqualValues(len(b)+len(b2), len(read))
   359  		s.True(bytes.Equal(append(b, b2...), read))
   360  
   361  		b3 := make([]byte, 1024)
   362  		for i := range b3 {
   363  			b3[i] = 'C'
   364  		}
   365  
   366  		written, err = s.backend.AppendFile(bytes.NewReader(b3), path)
   367  		s.Nil(err)
   368  		s.EqualValues(int64(len(b3)), written)
   369  
   370  		read, err = s.backend.ReadFile(path)
   371  		s.Nil(err)
   372  		s.EqualValues(len(b)+len(b2)+len(b3), len(read))
   373  		s.True(bytes.Equal(append(append(b, b2...), b3...), read))
   374  	})
   375  }
   376  
   377  func (s *FileBackendTestSuite) TestFileSize() {
   378  	s.Run("nonexistent file", func() {
   379  		size, err := s.backend.FileSize("tests/nonexistentfile")
   380  		s.NotNil(err)
   381  		s.Zero(size)
   382  	})
   383  
   384  	s.Run("valid file", func() {
   385  		data := make([]byte, rand.Intn(1024*1024)+1)
   386  		path := "tests/" + randomString()
   387  
   388  		written, err := s.backend.WriteFile(bytes.NewReader(data), path)
   389  		s.Nil(err)
   390  		s.EqualValues(len(data), written)
   391  		defer s.backend.RemoveFile(path)
   392  
   393  		size, err := s.backend.FileSize(path)
   394  		s.Nil(err)
   395  		s.Equal(int64(len(data)), size)
   396  	})
   397  }
   398  
   399  func (s *FileBackendTestSuite) TestFileModTime() {
   400  	s.Run("nonexistent file", func() {
   401  		modTime, err := s.backend.FileModTime("tests/nonexistentfile")
   402  		s.NotNil(err)
   403  		s.Empty(modTime)
   404  	})
   405  
   406  	s.Run("valid file", func() {
   407  		path := "tests/" + randomString()
   408  		data := []byte("some data")
   409  
   410  		written, err := s.backend.WriteFile(bytes.NewReader(data), path)
   411  		s.Nil(err)
   412  		s.EqualValues(len(data), written)
   413  		defer s.backend.RemoveFile(path)
   414  
   415  		modTime, err := s.backend.FileModTime(path)
   416  		s.Nil(err)
   417  		s.NotEmpty(modTime)
   418  
   419  		// We wait 1 second so that the times will differ enough to be testable.
   420  		time.Sleep(1 * time.Second)
   421  
   422  		path2 := "tests/" + randomString()
   423  		written, err = s.backend.WriteFile(bytes.NewReader(data), path2)
   424  		s.Nil(err)
   425  		s.EqualValues(len(data), written)
   426  		defer s.backend.RemoveFile(path2)
   427  
   428  		modTime2, err := s.backend.FileModTime(path2)
   429  		s.Nil(err)
   430  		s.NotEmpty(modTime2)
   431  		s.True(modTime2.After(modTime))
   432  	})
   433  }
   434  
   435  func BenchmarkS3WriteFile(b *testing.B) {
   436  	settings := FileBackendSettings{
   437  		DriverName:              driverS3,
   438  		AmazonS3AccessKeyId:     "minioaccesskey",
   439  		AmazonS3SecretAccessKey: "miniosecretkey",
   440  		AmazonS3Bucket:          "mattermost-test",
   441  		AmazonS3Region:          "",
   442  		AmazonS3Endpoint:        "localhost:9000",
   443  		AmazonS3PathPrefix:      "",
   444  		AmazonS3SSL:             false,
   445  		AmazonS3SSE:             false,
   446  	}
   447  
   448  	backend, err := NewFileBackend(settings)
   449  	require.NoError(b, err)
   450  
   451  	// This is needed to create the bucket if it doesn't exist.
   452  	require.NoError(b, backend.TestConnection())
   453  
   454  	path := "tests/" + randomString()
   455  	size := 1 * 1024 * 1024
   456  	data := make([]byte, size)
   457  
   458  	b.ResetTimer()
   459  
   460  	for i := 0; i < b.N; i++ {
   461  		written, err := backend.WriteFile(bytes.NewReader(data), path)
   462  		defer backend.RemoveFile(path)
   463  		require.NoError(b, err)
   464  		require.Equal(b, len(data), int(written))
   465  	}
   466  
   467  	b.StopTimer()
   468  }