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 }