github.com/cloudreve/Cloudreve/v3@v3.0.0-20240224133659-3edb00a6484c/pkg/filesystem/manage_test.go (about) 1 package filesystem 2 3 import ( 4 "context" 5 "errors" 6 "github.com/DATA-DOG/go-sqlmock" 7 "os" 8 "testing" 9 10 "github.com/cloudreve/Cloudreve/v3/pkg/filesystem/response" 11 testMock "github.com/stretchr/testify/mock" 12 13 model "github.com/cloudreve/Cloudreve/v3/models" 14 "github.com/cloudreve/Cloudreve/v3/pkg/cache" 15 "github.com/cloudreve/Cloudreve/v3/pkg/conf" 16 "github.com/cloudreve/Cloudreve/v3/pkg/filesystem/fsctx" 17 "github.com/cloudreve/Cloudreve/v3/pkg/serializer" 18 "github.com/cloudreve/Cloudreve/v3/pkg/util" 19 "github.com/jinzhu/gorm" 20 "github.com/stretchr/testify/assert" 21 ) 22 23 func TestFileSystem_ListPhysical(t *testing.T) { 24 asserts := assert.New(t) 25 fs := &FileSystem{ 26 User: &model.User{ 27 Model: gorm.Model{ 28 ID: 1, 29 }, 30 }, 31 Policy: &model.Policy{Type: "mock"}, 32 } 33 ctx := context.Background() 34 35 // 未知存储策略 36 { 37 fs.Policy.Type = "unknown" 38 res, err := fs.ListPhysical(ctx, "/") 39 asserts.Equal(ErrUnknownPolicyType, err) 40 asserts.Empty(res) 41 fs.Policy.Type = "mock" 42 } 43 44 // 无法列取目录 45 { 46 testHandler := new(FileHeaderMock) 47 testHandler.On("List", testMock.Anything, "/", testMock.Anything).Return([]response.Object{}, errors.New("error")) 48 fs.Handler = testHandler 49 res, err := fs.ListPhysical(ctx, "/") 50 asserts.EqualError(err, "error") 51 asserts.Empty(res) 52 } 53 54 // 成功 55 { 56 testHandler := new(FileHeaderMock) 57 testHandler.On("List", testMock.Anything, "/", testMock.Anything).Return( 58 []response.Object{{IsDir: true, Name: "1"}, {IsDir: false, Name: "2"}}, 59 nil, 60 ) 61 fs.Handler = testHandler 62 res, err := fs.ListPhysical(ctx, "/") 63 asserts.NoError(err) 64 asserts.Len(res, 1) 65 asserts.Equal("1", res[0].Name) 66 } 67 } 68 69 func TestFileSystem_List(t *testing.T) { 70 asserts := assert.New(t) 71 fs := &FileSystem{User: &model.User{ 72 Model: gorm.Model{ 73 ID: 1, 74 }, 75 }} 76 ctx := context.Background() 77 78 // 成功,子目录包含文件和路径,不使用路径处理钩子 79 // 根目录 80 mock.ExpectQuery("SELECT(.+)"). 81 WithArgs(1). 82 WillReturnRows(sqlmock.NewRows([]string{"id", "name", "owner_id"}).AddRow(1, "/", 1)) 83 // folder 84 mock.ExpectQuery("SELECT(.+)"). 85 WithArgs(1, 1, "folder"). 86 WillReturnRows(sqlmock.NewRows([]string{"id", "name", "owner_id"}).AddRow(5, "folder", 1)) 87 88 mock.ExpectQuery("SELECT(.+)folder(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(6, "sub_folder1").AddRow(7, "sub_folder2")) 89 mock.ExpectQuery("SELECT(.+)file(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(6, "sub_file1.txt").AddRow(7, "sub_file2.txt")) 90 objects, err := fs.List(ctx, "/folder", nil) 91 asserts.Len(objects, 4) 92 asserts.NoError(err) 93 asserts.NoError(mock.ExpectationsWereMet()) 94 95 // 成功,子目录包含文件和路径,不使用路径处理钩子,包含分享key 96 // 根目录 97 mock.ExpectQuery("SELECT(.+)"). 98 WithArgs(1). 99 WillReturnRows(sqlmock.NewRows([]string{"id", "name", "owner_id"}).AddRow(1, "/", 1)) 100 // folder 101 mock.ExpectQuery("SELECT(.+)"). 102 WithArgs(1, 1, "folder"). 103 WillReturnRows(sqlmock.NewRows([]string{"id", "name", "owner_id"}).AddRow(5, "folder", 1)) 104 105 mock.ExpectQuery("SELECT(.+)folder(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(6, "sub_folder1").AddRow(7, "sub_folder2")) 106 mock.ExpectQuery("SELECT(.+)file(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(6, "sub_file1.txt").AddRow(7, "sub_file2.txt")) 107 ctxWithKey := context.WithValue(ctx, fsctx.ShareKeyCtx, "share") 108 objects, err = fs.List(ctxWithKey, "/folder", nil) 109 asserts.Len(objects, 4) 110 asserts.Equal("share", objects[3].Key) 111 asserts.NoError(err) 112 asserts.NoError(mock.ExpectationsWereMet()) 113 114 // 成功,子目录包含文件和路径,使用路径处理钩子 115 mock.ExpectQuery("SELECT(.+)"). 116 WithArgs(1). 117 WillReturnRows(sqlmock.NewRows([]string{"id", "name", "owner_id"}).AddRow(1, "/", 1)) 118 // folder 119 mock.ExpectQuery("SELECT(.+)"). 120 WithArgs(1, 1, "folder"). 121 WillReturnRows(sqlmock.NewRows([]string{"id", "name", "owner_id"}).AddRow(2, "folder", 1)) 122 123 mock.ExpectQuery("SELECT(.+)folder(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "position"}).AddRow(6, "sub_folder1", "/folder").AddRow(7, "sub_folder2", "/folder")) 124 mock.ExpectQuery("SELECT(.+)file(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "dir"}).AddRow(6, "sub_file1.txt", "/folder").AddRow(7, "sub_file2.txt", "/folder")) 125 objects, err = fs.List(ctx, "/folder", func(s string) string { 126 return "prefix" + s 127 }) 128 asserts.Len(objects, 4) 129 asserts.NoError(err) 130 asserts.NoError(mock.ExpectationsWereMet()) 131 for _, value := range objects { 132 asserts.Contains(value.Path, "prefix/") 133 } 134 135 // 成功,子目录包含路径,使用路径处理钩子 136 mock.ExpectQuery("SELECT(.+)"). 137 WithArgs(1). 138 WillReturnRows(sqlmock.NewRows([]string{"id", "name", "owner_id"}).AddRow(1, "/", 1)) 139 // folder 140 mock.ExpectQuery("SELECT(.+)"). 141 WithArgs(1, 1, "folder"). 142 WillReturnRows(sqlmock.NewRows([]string{"id", "name", "owner_id"}).AddRow(2, "folder", 1)) 143 144 mock.ExpectQuery("SELECT(.+)folder(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "position"})) 145 mock.ExpectQuery("SELECT(.+)file(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "dir"}).AddRow(6, "sub_file1.txt", "/folder").AddRow(7, "sub_file2.txt", "/folder")) 146 objects, err = fs.List(ctx, "/folder", func(s string) string { 147 return "prefix" + s 148 }) 149 asserts.Len(objects, 2) 150 asserts.NoError(err) 151 asserts.NoError(mock.ExpectationsWereMet()) 152 for _, value := range objects { 153 asserts.Contains(value.Path, "prefix/") 154 } 155 156 // 成功,子目录下为空,使用路径处理钩子 157 mock.ExpectQuery("SELECT(.+)"). 158 WithArgs(1). 159 WillReturnRows(sqlmock.NewRows([]string{"id", "name", "owner_id"}).AddRow(1, "/", 1)) 160 // folder 161 mock.ExpectQuery("SELECT(.+)"). 162 WithArgs(1, 1, "folder"). 163 WillReturnRows(sqlmock.NewRows([]string{"id", "name", "owner_id"}).AddRow(2, "folder", 1)) 164 165 mock.ExpectQuery("SELECT(.+)folder(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "position"})) 166 mock.ExpectQuery("SELECT(.+)file(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "dir"})) 167 objects, err = fs.List(ctx, "/folder", func(s string) string { 168 return "prefix" + s 169 }) 170 asserts.Len(objects, 0) 171 asserts.NoError(err) 172 asserts.NoError(mock.ExpectationsWereMet()) 173 174 // 成功,子目录路径不存在 175 mock.ExpectQuery("SELECT(.+)"). 176 WithArgs(1). 177 WillReturnRows(sqlmock.NewRows([]string{"id", "name", "owner_id"}).AddRow(1, "/", 1)) 178 // folder 179 mock.ExpectQuery("SELECT(.+)"). 180 WithArgs(1, 1, "folder"). 181 WillReturnRows(sqlmock.NewRows([]string{"id", "name", "owner_id"})) 182 183 objects, err = fs.List(ctx, "/folder", func(s string) string { 184 return "prefix" + s 185 }) 186 asserts.Len(objects, 0) 187 asserts.NoError(mock.ExpectationsWereMet()) 188 } 189 190 func TestFileSystem_CreateDirectory(t *testing.T) { 191 asserts := assert.New(t) 192 fs := &FileSystem{User: &model.User{ 193 Model: gorm.Model{ 194 ID: 1, 195 }, 196 }} 197 ctx := context.Background() 198 199 // 目录名非法 200 _, err := fs.CreateDirectory(ctx, "/ad/a+?") 201 asserts.Equal(ErrIllegalObjectName, err) 202 203 // 存在同名文件 204 // 根目录 205 mock.ExpectQuery("SELECT(.+)"). 206 WithArgs(1). 207 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) 208 // ad 209 mock.ExpectQuery("SELECT(.+)"). 210 WithArgs(1, 1, "ad"). 211 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(2, 1)) 212 213 mock.ExpectQuery("SELECT(.+)files").WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(1, "ab")) 214 _, err = fs.CreateDirectory(ctx, "/ad/ab") 215 asserts.Equal(ErrFileExisted, err) 216 asserts.NoError(mock.ExpectationsWereMet()) 217 218 // 存在同名目录,直接返回 219 mock.ExpectQuery("SELECT(.+)"). 220 WithArgs(1). 221 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) 222 // ad 223 mock.ExpectQuery("SELECT(.+)"). 224 WithArgs(1, 1, "ad"). 225 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(2, 1)) 226 227 mock.ExpectQuery("SELECT(.+)files").WillReturnRows(sqlmock.NewRows([]string{"id", "name"})) 228 // ab 229 mock.ExpectQuery("SELECT(.+)"). 230 WithArgs("ab", 2, 1). 231 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(3, 1)) 232 res, err := fs.CreateDirectory(ctx, "/ad/ab") 233 asserts.NoError(err) 234 asserts.EqualValues(3, res.ID) 235 asserts.NoError(mock.ExpectationsWereMet()) 236 237 // 成功创建 238 mock.ExpectQuery("SELECT(.+)"). 239 WithArgs(1). 240 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) 241 // ad 242 mock.ExpectQuery("SELECT(.+)"). 243 WithArgs(1, 1, "ad"). 244 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(2, 1)) 245 246 mock.ExpectQuery("SELECT(.+)files").WillReturnRows(sqlmock.NewRows([]string{"id", "name"})) 247 mock.ExpectQuery("SELECT(.+)"). 248 WithArgs("ab", 2, 1). 249 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"})) 250 mock.ExpectBegin() 251 mock.ExpectExec("INSERT(.+)").WillReturnResult(sqlmock.NewResult(1, 1)) 252 mock.ExpectCommit() 253 _, err = fs.CreateDirectory(ctx, "/ad/ab") 254 asserts.NoError(err) 255 asserts.NoError(mock.ExpectationsWereMet()) 256 257 // 成功创建, 递归创建父目录 258 // 根目录 259 mock.ExpectQuery("SELECT(.+)"). 260 WithArgs(1). 261 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) 262 // ad 263 mock.ExpectQuery("SELECT(.+)"). 264 WithArgs(1, 1, "ad"). 265 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"})) 266 // 根目录 267 mock.ExpectQuery("SELECT(.+)"). 268 WithArgs(1). 269 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) 270 mock.ExpectQuery("SELECT(.+)files").WillReturnRows(sqlmock.NewRows([]string{"id", "name"})) 271 // 创建ad 272 mock.ExpectQuery("SELECT(.+)"). 273 WithArgs("ad", 1, 1). 274 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"})) 275 mock.ExpectBegin() 276 mock.ExpectExec("INSERT(.+)").WillReturnResult(sqlmock.NewResult(2, 1)) 277 mock.ExpectCommit() 278 mock.ExpectQuery("SELECT(.+)files").WillReturnRows(sqlmock.NewRows([]string{"id", "name"})) 279 // 创建ab 280 mock.ExpectQuery("SELECT(.+)"). 281 WithArgs("ab", 2, 1). 282 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"})) 283 mock.ExpectBegin() 284 mock.ExpectExec("INSERT(.+)").WillReturnResult(sqlmock.NewResult(1, 1)) 285 mock.ExpectCommit() 286 _, err = fs.CreateDirectory(ctx, "/ad/ab") 287 asserts.NoError(err) 288 asserts.NoError(mock.ExpectationsWereMet()) 289 290 // 底层创建失败 291 // 成功创建 292 mock.ExpectQuery("SELECT(.+)"). 293 WithArgs(1). 294 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) 295 // ad 296 mock.ExpectQuery("SELECT(.+)"). 297 WithArgs(1, 1, "ad"). 298 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"})) 299 // 根目录 300 mock.ExpectQuery("SELECT(.+)"). 301 WithArgs(1). 302 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) 303 mock.ExpectQuery("SELECT(.+)files").WillReturnRows(sqlmock.NewRows([]string{"id", "name"})) 304 // 创建ad 305 mock.ExpectQuery("SELECT(.+)"). 306 WithArgs("ad", 1, 1). 307 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"})) 308 mock.ExpectBegin() 309 mock.ExpectExec("INSERT(.+)").WillReturnResult(sqlmock.NewResult(2, 1)).WillReturnError(errors.New("error")) 310 mock.ExpectRollback() 311 mock.ExpectQuery("SELECT(.+)"). 312 WillReturnError(errors.New("error")) 313 _, err = fs.CreateDirectory(ctx, "/ad/ab") 314 asserts.Error(err) 315 asserts.NoError(mock.ExpectationsWereMet()) 316 317 // 直接创建根目录 318 mock.ExpectQuery("SELECT(.+)"). 319 WithArgs(1). 320 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) 321 _, err = fs.CreateDirectory(ctx, "/") 322 asserts.NoError(err) 323 asserts.NoError(mock.ExpectationsWereMet()) 324 325 // 直接创建根目录, 重设根目录 326 fs.Root = &model.Folder{} 327 _, err = fs.CreateDirectory(ctx, "/") 328 asserts.NoError(err) 329 asserts.NoError(mock.ExpectationsWereMet()) 330 } 331 332 func TestFileSystem_ListDeleteFiles(t *testing.T) { 333 conf.DatabaseConfig.Type = "mysql" 334 asserts := assert.New(t) 335 fs := &FileSystem{User: &model.User{ 336 Model: gorm.Model{ 337 ID: 1, 338 }, 339 }} 340 341 // 成功 342 { 343 mock.ExpectQuery("SELECT(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(1, "1.txt").AddRow(2, "2.txt")) 344 err := fs.ListDeleteFiles(context.Background(), []uint{1}) 345 asserts.NoError(err) 346 asserts.NoError(mock.ExpectationsWereMet()) 347 } 348 349 // 失败 350 { 351 mock.ExpectQuery("SELECT(.+)").WillReturnError(errors.New("error")) 352 err := fs.ListDeleteFiles(context.Background(), []uint{1}) 353 asserts.Error(err) 354 asserts.Equal(serializer.CodeDBError, err.(serializer.AppError).Code) 355 asserts.NoError(mock.ExpectationsWereMet()) 356 } 357 } 358 359 func TestFileSystem_ListDeleteDirs(t *testing.T) { 360 conf.DatabaseConfig.Type = "mysql" 361 asserts := assert.New(t) 362 fs := &FileSystem{User: &model.User{ 363 Model: gorm.Model{ 364 ID: 1, 365 }, 366 }} 367 368 // 成功 369 { 370 mock.ExpectQuery("SELECT(.+)"). 371 WillReturnRows( 372 sqlmock.NewRows([]string{"id", "parent_id"}). 373 AddRow(1, 0). 374 AddRow(2, 0). 375 AddRow(3, 0), 376 ) 377 mock.ExpectQuery("SELECT(.+)files(.+)"). 378 WithArgs(1, 2, 3). 379 WillReturnRows( 380 sqlmock.NewRows([]string{"id", "name"}). 381 AddRow(4, "1.txt"). 382 AddRow(5, "2.txt"). 383 AddRow(6, "3.txt"), 384 ) 385 err := fs.ListDeleteDirs(context.Background(), []uint{1}) 386 asserts.NoError(err) 387 asserts.Len(fs.FileTarget, 3) 388 asserts.Len(fs.DirTarget, 3) 389 asserts.NoError(mock.ExpectationsWereMet()) 390 } 391 392 // 成功,忽略根目录 393 { 394 mock.ExpectQuery("SELECT(.+)"). 395 WillReturnRows( 396 sqlmock.NewRows([]string{"id", "parent_id"}). 397 AddRow(1, 0). 398 AddRow(2, nil). 399 AddRow(3, 0), 400 ) 401 mock.ExpectQuery("SELECT(.+)files(.+)"). 402 WithArgs(1, 3). 403 WillReturnRows( 404 sqlmock.NewRows([]string{"id", "name"}). 405 AddRow(4, "1.txt"). 406 AddRow(5, "2.txt"). 407 AddRow(6, "3.txt"), 408 ) 409 fs.CleanTargets() 410 err := fs.ListDeleteDirs(context.Background(), []uint{1}) 411 asserts.NoError(err) 412 asserts.Len(fs.FileTarget, 3) 413 asserts.Len(fs.DirTarget, 2) 414 asserts.NoError(mock.ExpectationsWereMet()) 415 } 416 417 // 检索文件发生错误 418 { 419 mock.ExpectQuery("SELECT(.+)"). 420 WillReturnRows( 421 sqlmock.NewRows([]string{"id", "parent_id"}). 422 AddRow(1, 0). 423 AddRow(2, 0). 424 AddRow(3, 0), 425 ) 426 mock.ExpectQuery("SELECT(.+)"). 427 WithArgs(1, 2, 3). 428 WillReturnError(errors.New("error")) 429 fs.CleanTargets() 430 err := fs.ListDeleteDirs(context.Background(), []uint{1}) 431 asserts.Error(err) 432 asserts.Len(fs.DirTarget, 3) 433 asserts.NoError(mock.ExpectationsWereMet()) 434 } 435 // 检索目录发生错误 436 { 437 mock.ExpectQuery("SELECT(.+)"). 438 WillReturnError(errors.New("error")) 439 err := fs.ListDeleteDirs(context.Background(), []uint{1}) 440 asserts.Error(err) 441 asserts.NoError(mock.ExpectationsWereMet()) 442 } 443 } 444 445 func TestFileSystem_Delete(t *testing.T) { 446 conf.DatabaseConfig.Type = "mysql" 447 asserts := assert.New(t) 448 cache.Set("pack_size_1", uint64(0), 0) 449 fs := &FileSystem{User: &model.User{ 450 Model: gorm.Model{ 451 ID: 0, 452 }, 453 Storage: 3, 454 Group: model.Group{MaxStorage: 3}, 455 }} 456 ctx := context.Background() 457 458 //全部未成功,强制 459 { 460 fs.CleanTargets() 461 mock.ExpectQuery("SELECT(.+)"). 462 WillReturnRows( 463 sqlmock.NewRows([]string{"id", "parent_id"}). 464 AddRow(1, 0). 465 AddRow(2, 0). 466 AddRow(3, 0), 467 ) 468 mock.ExpectQuery("SELECT(.+)"). 469 WithArgs(1, 2, 3). 470 WillReturnRows( 471 sqlmock.NewRows([]string{"id", "name", "source_name", "policy_id", "size"}). 472 AddRow(4, "1.txt", "1.txt", 365, 1), 473 ) 474 mock.ExpectQuery("SELECT(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "source_name", "policy_id", "size"}).AddRow(1, "2.txt", "2.txt", 365, 2)) 475 // 两次查询软连接 476 mock.ExpectQuery("SELECT(.+)files(.+)"). 477 WillReturnRows(sqlmock.NewRows([]string{"id", "policy_id", "source_name"})) 478 mock.ExpectQuery("SELECT(.+)files(.+)"). 479 WillReturnRows(sqlmock.NewRows([]string{"id", "policy_id", "source_name"})) 480 // 查询上传策略 481 mock.ExpectQuery("SELECT(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "type"}).AddRow(365, "local")) 482 // 删除文件记录 483 mock.ExpectBegin() 484 mock.ExpectExec("DELETE(.+)"). 485 WillReturnResult(sqlmock.NewResult(0, 1)) 486 mock.ExpectExec("DELETE(.+)"). 487 WillReturnResult(sqlmock.NewResult(0, 1)) 488 mock.ExpectCommit() 489 // 删除对应分享 490 mock.ExpectBegin() 491 mock.ExpectExec("UPDATE(.+)shares"). 492 WillReturnResult(sqlmock.NewResult(0, 3)) 493 mock.ExpectCommit() 494 // 删除目录 495 mock.ExpectBegin() 496 mock.ExpectExec("DELETE(.+)"). 497 WillReturnResult(sqlmock.NewResult(0, 3)) 498 mock.ExpectCommit() 499 // 删除对应分享 500 mock.ExpectBegin() 501 mock.ExpectExec("UPDATE(.+)shares"). 502 WillReturnResult(sqlmock.NewResult(0, 3)) 503 mock.ExpectCommit() 504 505 fs.FileTarget = []model.File{} 506 fs.DirTarget = []model.Folder{} 507 err := fs.Delete(ctx, []uint{1}, []uint{1}, true, false) 508 asserts.NoError(err) 509 } 510 //全部成功 511 { 512 fs.CleanTargets() 513 file, err := os.Create(util.RelativePath("1.txt")) 514 file2, err := os.Create(util.RelativePath("2.txt")) 515 file.Close() 516 file2.Close() 517 asserts.NoError(err) 518 mock.ExpectQuery("SELECT(.+)"). 519 WillReturnRows( 520 sqlmock.NewRows([]string{"id", "parent_id"}). 521 AddRow(1, 0). 522 AddRow(2, 0). 523 AddRow(3, 0), 524 ) 525 mock.ExpectQuery("SELECT(.+)"). 526 WithArgs(1, 2, 3). 527 WillReturnRows( 528 sqlmock.NewRows([]string{"id", "name", "source_name", "policy_id", "size"}). 529 AddRow(4, "1.txt", "1.txt", 602, 1), 530 ) 531 mock.ExpectQuery("SELECT(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "source_name", "policy_id", "size"}).AddRow(1, "2.txt", "2.txt", 602, 2)) 532 // 两次查询软连接 533 mock.ExpectQuery("SELECT(.+)files(.+)"). 534 WillReturnRows(sqlmock.NewRows([]string{"id", "policy_id", "source_name"})) 535 mock.ExpectQuery("SELECT(.+)files(.+)"). 536 WillReturnRows(sqlmock.NewRows([]string{"id", "policy_id", "source_name"})) 537 // 查询上传策略 538 mock.ExpectQuery("SELECT(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "type"}).AddRow(602, "local")) 539 // 删除文件记录 540 mock.ExpectBegin() 541 mock.ExpectExec("DELETE(.+)"). 542 WillReturnResult(sqlmock.NewResult(0, 1)) 543 mock.ExpectExec("DELETE(.+)"). 544 WillReturnResult(sqlmock.NewResult(0, 1)) 545 mock.ExpectCommit() 546 // 删除对应分享 547 mock.ExpectBegin() 548 mock.ExpectExec("UPDATE(.+)shares"). 549 WillReturnResult(sqlmock.NewResult(0, 3)) 550 mock.ExpectCommit() 551 // 删除目录 552 mock.ExpectBegin() 553 mock.ExpectExec("DELETE(.+)"). 554 WillReturnResult(sqlmock.NewResult(0, 3)) 555 mock.ExpectCommit() 556 // 删除对应分享 557 mock.ExpectBegin() 558 mock.ExpectExec("UPDATE(.+)shares"). 559 WillReturnResult(sqlmock.NewResult(0, 3)) 560 mock.ExpectCommit() 561 562 fs.FileTarget = []model.File{} 563 fs.DirTarget = []model.Folder{} 564 err = fs.Delete(ctx, []uint{1}, []uint{1}, false, false) 565 asserts.NoError(err) 566 } 567 568 } 569 570 func TestFileSystem_Copy(t *testing.T) { 571 asserts := assert.New(t) 572 cache.Set("pack_size_1", uint64(0), 0) 573 fs := &FileSystem{User: &model.User{ 574 Model: gorm.Model{ 575 ID: 1, 576 }, 577 Storage: 3, 578 Group: model.Group{MaxStorage: 3}, 579 }} 580 ctx := context.Background() 581 582 // 目录不存在 583 { 584 mock.ExpectQuery("SELECT(.+)").WillReturnRows( 585 sqlmock.NewRows([]string{"name"}), 586 ) 587 mock.ExpectQuery("SELECT(.+)").WillReturnRows( 588 sqlmock.NewRows([]string{"name"}), 589 ) 590 err := fs.Copy(ctx, []uint{}, []uint{}, "/src", "/dst") 591 asserts.Equal(ErrPathNotExist, err) 592 asserts.NoError(mock.ExpectationsWereMet()) 593 } 594 595 // 复制目录出错 596 { 597 // 根目录 598 mock.ExpectQuery("SELECT(.+)"). 599 WithArgs(1). 600 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) 601 // 1 602 mock.ExpectQuery("SELECT(.+)"). 603 WithArgs(1, 1, "dst"). 604 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(2, 1)) 605 // 根目录 606 mock.ExpectQuery("SELECT(.+)"). 607 WithArgs(1). 608 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) 609 // 1 610 mock.ExpectQuery("SELECT(.+)"). 611 WithArgs(1, 1, "src"). 612 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(2, 1)) 613 614 err := fs.Copy(ctx, []uint{1}, []uint{}, "/src", "/dst") 615 asserts.Error(err) 616 asserts.NoError(mock.ExpectationsWereMet()) 617 } 618 619 } 620 621 func TestFileSystem_Move(t *testing.T) { 622 asserts := assert.New(t) 623 cache.Set("pack_size_1", uint64(0), 0) 624 fs := &FileSystem{User: &model.User{ 625 Model: gorm.Model{ 626 ID: 1, 627 }, 628 Storage: 3, 629 Group: model.Group{MaxStorage: 3}, 630 }} 631 ctx := context.Background() 632 633 // 目录不存在 634 { 635 mock.ExpectQuery("SELECT(.+)").WillReturnRows( 636 sqlmock.NewRows([]string{"name"}), 637 ) 638 err := fs.Move(ctx, []uint{}, []uint{}, "/src", "/dst") 639 asserts.Equal(ErrPathNotExist, err) 640 asserts.NoError(mock.ExpectationsWereMet()) 641 } 642 643 // 移动目录出错 644 { 645 // 根目录 646 mock.ExpectQuery("SELECT(.+)"). 647 WithArgs(1). 648 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) 649 // 1 650 mock.ExpectQuery("SELECT(.+)"). 651 WithArgs(1, 1, "dst"). 652 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(2, 1)) 653 // 根目录 654 mock.ExpectQuery("SELECT(.+)"). 655 WithArgs(1). 656 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) 657 // 1 658 mock.ExpectQuery("SELECT(.+)"). 659 WithArgs(1, 1, "src"). 660 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(2, 1)) 661 err := fs.Move(ctx, []uint{1}, []uint{}, "/src", "/dst") 662 asserts.Error(err) 663 asserts.NoError(mock.ExpectationsWereMet()) 664 } 665 } 666 667 func TestFileSystem_Rename(t *testing.T) { 668 asserts := assert.New(t) 669 fs := &FileSystem{User: &model.User{ 670 Model: gorm.Model{ 671 ID: 1, 672 }, 673 }, 674 Policy: &model.Policy{}, 675 } 676 ctx := context.Background() 677 678 // 重命名文件 成功 679 { 680 mock.ExpectQuery("SELECT(.+)files(.+)"). 681 WithArgs(10, 1). 682 WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(10, "old.text")) 683 mock.ExpectBegin() 684 mock.ExpectExec("UPDATE(.+)files(.+)SET(.+)"). 685 WithArgs(sqlmock.AnyArg(), "new.txt", sqlmock.AnyArg(), 10). 686 WillReturnResult(sqlmock.NewResult(1, 1)) 687 mock.ExpectCommit() 688 err := fs.Rename(ctx, []uint{}, []uint{10}, "new.txt") 689 asserts.NoError(mock.ExpectationsWereMet()) 690 asserts.NoError(err) 691 } 692 693 // 重命名文件 不存在 694 { 695 mock.ExpectQuery("SELECT(.+)files(.+)"). 696 WithArgs(10, 1). 697 WillReturnRows(sqlmock.NewRows([]string{"id", "name"})) 698 err := fs.Rename(ctx, []uint{}, []uint{10}, "new.txt") 699 asserts.NoError(mock.ExpectationsWereMet()) 700 asserts.Error(err) 701 asserts.Equal(ErrPathNotExist, err) 702 } 703 704 // 重命名文件 失败 705 { 706 mock.ExpectQuery("SELECT(.+)files(.+)"). 707 WithArgs(10, 1). 708 WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(10, "old.text")) 709 mock.ExpectBegin() 710 mock.ExpectExec("UPDATE(.+)files(.+)SET(.+)"). 711 WithArgs(sqlmock.AnyArg(), "new.txt", sqlmock.AnyArg(), 10). 712 WillReturnError(errors.New("error")) 713 mock.ExpectRollback() 714 err := fs.Rename(ctx, []uint{}, []uint{10}, "new.txt") 715 asserts.NoError(mock.ExpectationsWereMet()) 716 asserts.Error(err) 717 asserts.Equal(ErrFileExisted, err) 718 } 719 720 // 重命名目录 成功 721 { 722 mock.ExpectQuery("SELECT(.+)folders(.+)"). 723 WithArgs(10, 1). 724 WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(10, "old")) 725 mock.ExpectBegin() 726 mock.ExpectExec("UPDATE(.+)folders(.+)SET(.+)"). 727 WithArgs("new", 10). 728 WillReturnResult(sqlmock.NewResult(1, 1)) 729 mock.ExpectCommit() 730 err := fs.Rename(ctx, []uint{10}, []uint{}, "new") 731 asserts.NoError(mock.ExpectationsWereMet()) 732 asserts.NoError(err) 733 } 734 735 // 重命名目录 不存在 736 { 737 mock.ExpectQuery("SELECT(.+)folders(.+)"). 738 WithArgs(10, 1). 739 WillReturnRows(sqlmock.NewRows([]string{"id", "name"})) 740 err := fs.Rename(ctx, []uint{10}, []uint{}, "new") 741 asserts.NoError(mock.ExpectationsWereMet()) 742 asserts.Error(err) 743 asserts.Equal(ErrPathNotExist, err) 744 } 745 746 // 重命名目录 失败 747 { 748 mock.ExpectQuery("SELECT(.+)folders(.+)"). 749 WithArgs(10, 1). 750 WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(10, "old")) 751 mock.ExpectBegin() 752 mock.ExpectExec("UPDATE(.+)folders(.+)SET(.+)"). 753 WithArgs("new", 10). 754 WillReturnError(errors.New("error")) 755 mock.ExpectRollback() 756 err := fs.Rename(ctx, []uint{10}, []uint{}, "new") 757 asserts.NoError(mock.ExpectationsWereMet()) 758 asserts.Error(err) 759 asserts.Equal(ErrFileExisted, err) 760 } 761 762 // 未选中任何对象 763 { 764 err := fs.Rename(ctx, []uint{}, []uint{}, "new") 765 asserts.Error(err) 766 asserts.Equal(ErrPathNotExist, err) 767 } 768 769 // 新名字是目录,不合法 770 { 771 err := fs.Rename(ctx, []uint{10}, []uint{}, "ne/w") 772 asserts.Error(err) 773 asserts.Equal(ErrIllegalObjectName, err) 774 } 775 776 // 新名字是文件,不合法 777 { 778 err := fs.Rename(ctx, []uint{}, []uint{10}, "ne/w") 779 asserts.Error(err) 780 asserts.Equal(ErrIllegalObjectName, err) 781 } 782 783 // 新名字是文件,扩展名不合法 784 { 785 fs.Policy.OptionsSerialized.FileType = []string{"txt"} 786 err := fs.Rename(ctx, []uint{}, []uint{10}, "1.jpg") 787 asserts.Error(err) 788 asserts.Equal(ErrIllegalObjectName, err) 789 } 790 791 // 新名字是目录,不应该检测扩展名 792 { 793 fs.Policy.OptionsSerialized.FileType = []string{"txt"} 794 mock.ExpectQuery("SELECT(.+)folders(.+)"). 795 WithArgs(10, 1). 796 WillReturnRows(sqlmock.NewRows([]string{"id", "name"})) 797 err := fs.Rename(ctx, []uint{10}, []uint{}, "new") 798 asserts.NoError(mock.ExpectationsWereMet()) 799 asserts.Error(err) 800 asserts.Equal(ErrPathNotExist, err) 801 } 802 } 803 804 func TestFileSystem_SaveTo(t *testing.T) { 805 asserts := assert.New(t) 806 fs := &FileSystem{User: &model.User{ 807 Model: gorm.Model{ 808 ID: 1, 809 }, 810 }} 811 ctx := context.Background() 812 813 // 单文件 失败 814 { 815 // 根目录 816 mock.ExpectQuery("SELECT(.+)"). 817 WithArgs(1). 818 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) 819 mock.ExpectQuery("SELECT(.+)").WillReturnError(errors.New("error")) 820 fs.SetTargetFile(&[]model.File{{Name: "test.txt"}}) 821 err := fs.SaveTo(ctx, "/") 822 asserts.NoError(mock.ExpectationsWereMet()) 823 asserts.Error(err) 824 } 825 // 目录 成功 826 { 827 // 根目录 828 mock.ExpectQuery("SELECT(.+)"). 829 WithArgs(1). 830 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) 831 mock.ExpectQuery("SELECT(.+)").WillReturnError(errors.New("error")) 832 fs.SetTargetDir(&[]model.Folder{{Name: "folder"}}) 833 err := fs.SaveTo(ctx, "/") 834 asserts.NoError(mock.ExpectationsWereMet()) 835 asserts.Error(err) 836 } 837 // 父目录不存在 838 { 839 // 根目录 840 mock.ExpectQuery("SELECT(.+)"). 841 WithArgs(1). 842 WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"})) 843 fs.SetTargetDir(&[]model.Folder{{Name: "folder"}}) 844 err := fs.SaveTo(ctx, "/") 845 asserts.NoError(mock.ExpectationsWereMet()) 846 asserts.Error(err) 847 } 848 }