package local import ( "context" model "github.com/cloudreve/Cloudreve/v3/models" "github.com/cloudreve/Cloudreve/v3/pkg/auth" "github.com/cloudreve/Cloudreve/v3/pkg/filesystem/driver" "github.com/cloudreve/Cloudreve/v3/pkg/filesystem/fsctx" "github.com/cloudreve/Cloudreve/v3/pkg/serializer" "github.com/cloudreve/Cloudreve/v3/pkg/util" "github.com/jinzhu/gorm" "github.com/stretchr/testify/assert" "io" "os" "strings" "testing" ) func TestHandler_Put(t *testing.T) { asserts := assert.New(t) handler := Driver{} defer func() { os.Remove(util.RelativePath("TestHandler_Put.txt")) os.Remove(util.RelativePath("inner/TestHandler_Put.txt")) }() testCases := []struct { file fsctx.FileHeader errContains string }{ {&fsctx.FileStream{ SavePath: "TestHandler_Put.txt", File: io.NopCloser(strings.NewReader("")), }, ""}, {&fsctx.FileStream{ SavePath: "TestHandler_Put.txt", File: io.NopCloser(strings.NewReader("")), }, "file with the same name existed or unavailable"}, {&fsctx.FileStream{ SavePath: "inner/TestHandler_Put.txt", File: io.NopCloser(strings.NewReader("")), }, ""}, {&fsctx.FileStream{ Mode: fsctx.Append | fsctx.Overwrite, SavePath: "inner/TestHandler_Put.txt", File: io.NopCloser(strings.NewReader("123")), }, ""}, {&fsctx.FileStream{ AppendStart: 10, Mode: fsctx.Append | fsctx.Overwrite, SavePath: "inner/TestHandler_Put.txt", File: io.NopCloser(strings.NewReader("123")), }, "size of unfinished uploaded chunks is not as expected"}, {&fsctx.FileStream{ Mode: fsctx.Append | fsctx.Overwrite, SavePath: "inner/TestHandler_Put.txt", File: io.NopCloser(strings.NewReader("123")), }, ""}, } for _, testCase := range testCases { err := handler.Put(context.Background(), testCase.file) if testCase.errContains != "" { asserts.Error(err) asserts.Contains(err.Error(), testCase.errContains) } else { asserts.NoError(err) asserts.True(util.Exists(util.RelativePath(testCase.file.Info().SavePath))) } } } func TestDriver_TruncateFailed(t *testing.T) { a := assert.New(t) h := Driver{} a.Error(h.Truncate(context.Background(), "TestDriver_TruncateFailed", 0)) } func TestHandler_Delete(t *testing.T) { asserts := assert.New(t) handler := Driver{} ctx := context.Background() filePath := util.RelativePath("TestHandler_Delete.file") file, err := os.Create(filePath) asserts.NoError(err) _ = file.Close() list, err := handler.Delete(ctx, []string{"TestHandler_Delete.file"}) asserts.Equal([]string{}, list) asserts.NoError(err) file, err = os.Create(filePath) _ = file.Close() file, _ = os.OpenFile(filePath, os.O_RDWR, os.FileMode(0)) asserts.NoError(err) list, err = handler.Delete(ctx, []string{"TestHandler_Delete.file", "test.notexist"}) file.Close() asserts.Equal([]string{}, list) asserts.NoError(err) list, err = handler.Delete(ctx, []string{"test.notexist"}) asserts.Equal([]string{}, list) asserts.NoError(err) file, err = os.Create(filePath) asserts.NoError(err) list, err = handler.Delete(ctx, []string{"TestHandler_Delete.file"}) _ = file.Close() asserts.Equal([]string{}, list) asserts.NoError(err) } func TestHandler_Get(t *testing.T) { asserts := assert.New(t) handler := Driver{} ctx, cancel := context.WithCancel(context.Background()) defer cancel() // 成功 file, err := os.Create(util.RelativePath("TestHandler_Get.txt")) asserts.NoError(err) _ = file.Close() rs, err := handler.Get(ctx, "TestHandler_Get.txt") asserts.NoError(err) asserts.NotNil(rs) // 文件不存在 rs, err = handler.Get(ctx, "TestHandler_Get_notExist.txt") asserts.Error(err) asserts.Nil(rs) } func TestHandler_Thumb(t *testing.T) { asserts := assert.New(t) handler := Driver{} ctx := context.Background() file, err := os.Create(util.RelativePath("TestHandler_Thumb._thumb")) asserts.NoError(err) file.Close() f := &model.File{ SourceName: "TestHandler_Thumb", MetadataSerialized: map[string]string{ model.ThumbStatusMetadataKey: model.ThumbStatusExist, }, } // 正常 { thumb, err := handler.Thumb(ctx, f) asserts.NoError(err) asserts.NotNil(thumb.Content) } // file 不存在 { f.SourceName = "not_exist" _, err := handler.Thumb(ctx, f) asserts.Error(err) asserts.ErrorIs(err, driver.ErrorThumbNotExist) } // thumb not exist { f.MetadataSerialized[model.ThumbStatusMetadataKey] = model.ThumbStatusNotExist _, err := handler.Thumb(ctx, f) asserts.Error(err) asserts.ErrorIs(err, driver.ErrorThumbNotExist) } } func TestHandler_Source(t *testing.T) { asserts := assert.New(t) handler := Driver{ Policy: &model.Policy{}, } ctx := context.Background() auth.General = auth.HMACAuth{SecretKey: []byte("test")} // 成功 { file := model.File{ Model: gorm.Model{ ID: 1, }, Name: "test.jpg", } ctx := context.WithValue(ctx, fsctx.FileModelCtx, file) sourceURL, err := handler.Source(ctx, "", 0, false, 0) asserts.NoError(err) asserts.NotEmpty(sourceURL) asserts.Contains(sourceURL, "sign=") } // 下载 { file := model.File{ Model: gorm.Model{ ID: 1, }, Name: "test.jpg", } ctx := context.WithValue(ctx, fsctx.FileModelCtx, file) sourceURL, err := handler.Source(ctx, "", 0, true, 0) asserts.NoError(err) asserts.NotEmpty(sourceURL) asserts.Contains(sourceURL, "sign=") asserts.Contains(sourceURL, "download") } // 无法获取上下文 { sourceURL, err := handler.Source(ctx, "", 0, false, 0) asserts.Error(err) asserts.Empty(sourceURL) } // 设定了CDN { handler.Policy.BaseURL = "https://cqu.edu.cn" file := model.File{ Model: gorm.Model{ ID: 1, }, Name: "test.jpg", } ctx := context.WithValue(ctx, fsctx.FileModelCtx, file) sourceURL, err := handler.Source(ctx, "", 0, false, 0) asserts.NoError(err) asserts.NotEmpty(sourceURL) asserts.Contains(sourceURL, "sign=") asserts.Contains(sourceURL, "https://cqu.edu.cn") } // 设定了CDN,解析失败 { handler.Policy.BaseURL = string([]byte{0x7f}) file := model.File{ Model: gorm.Model{ ID: 1, }, Name: "test.jpg", } ctx := context.WithValue(ctx, fsctx.FileModelCtx, file) sourceURL, err := handler.Source(ctx, "", 0, false, 0) asserts.Error(err) asserts.Empty(sourceURL) } } func TestHandler_GetDownloadURL(t *testing.T) { asserts := assert.New(t) handler := Driver{Policy: &model.Policy{}} ctx := context.Background() auth.General = auth.HMACAuth{SecretKey: []byte("test")} // 成功 { file := model.File{ Model: gorm.Model{ ID: 1, }, Name: "test.jpg", } ctx := context.WithValue(ctx, fsctx.FileModelCtx, file) downloadURL, err := handler.Source(ctx, "", 10, true, 0) asserts.NoError(err) asserts.Contains(downloadURL, "sign=") } // 无法获取上下文 { downloadURL, err := handler.Source(ctx, "", 10, true, 0) asserts.Error(err) asserts.Empty(downloadURL) } } func TestHandler_Token(t *testing.T) { asserts := assert.New(t) handler := Driver{ Policy: &model.Policy{}, } ctx := context.Background() upSession := &serializer.UploadSession{SavePath: "TestHandler_Token"} _, err := handler.Token(ctx, 10, upSession, &fsctx.FileStream{}) asserts.NoError(err) file, _ := os.Create("TestHandler_Token") defer func() { file.Close() os.Remove("TestHandler_Token") }() _, err = handler.Token(ctx, 10, upSession, &fsctx.FileStream{}) asserts.Error(err) asserts.Contains(err.Error(), "already exist") } func TestDriver_CancelToken(t *testing.T) { a := assert.New(t) handler := Driver{} a.NoError(handler.CancelToken(context.Background(), &serializer.UploadSession{})) } func TestDriver_List(t *testing.T) { asserts := assert.New(t) handler := Driver{} ctx := context.Background() // 创建测试目录结构 for _, path := range []string{ "test/TestDriver_List/parent.txt", "test/TestDriver_List/parent_folder2/sub2.txt", "test/TestDriver_List/parent_folder1/sub_folder/sub1.txt", "test/TestDriver_List/parent_folder1/sub_folder/sub2.txt", } { f, _ := util.CreatNestedFile(util.RelativePath(path)) f.Close() } // 非递归列出 { res, err := handler.List(ctx, "test/TestDriver_List", false) asserts.NoError(err) asserts.Len(res, 3) } // 递归列出 { res, err := handler.List(ctx, "test/TestDriver_List", true) asserts.NoError(err) asserts.Len(res, 7) } }