test(thumb): new changes in filesystem pkg

This commit is contained in:
Aaron Liu
2023-04-13 19:39:12 +08:00
parent 408733a974
commit 8e2fc1a8f6
10 changed files with 195 additions and 212 deletions

View File

@@ -4,6 +4,7 @@ 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"
@@ -141,17 +142,34 @@ func TestHandler_Thumb(t *testing.T) {
asserts.NoError(err)
file.Close()
f := &model.File{
SourceName: "TestHandler_Thumb",
MetadataSerialized: map[string]string{
model.ThumbStatusMetadataKey: model.ThumbStatusExist,
},
}
// 正常
{
thumb, err := handler.Thumb(ctx, "TestHandler_Thumb")
thumb, err := handler.Thumb(ctx, f)
asserts.NoError(err)
asserts.NotNil(thumb.Content)
}
// 不存在
// file 不存在
{
_, err := handler.Thumb(ctx, "not_exist")
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)
}
}

View File

@@ -246,19 +246,19 @@ func TestDriver_Thumb(t *testing.T) {
}
handler.Client, _ = NewClient(&model.Policy{})
handler.Client.Credential.ExpiresIn = time.Now().Add(time.Duration(100) * time.Hour).Unix()
file := &model.File{PicInfo: "1,1", Model: gorm.Model{ID: 1}}
// 失败
{
ctx := context.WithValue(context.Background(), fsctx.ThumbSizeCtx, [2]uint{10, 20})
ctx = context.WithValue(ctx, fsctx.FileModelCtx, model.File{PicInfo: "1,1", Model: gorm.Model{ID: 1}})
res, err := handler.Thumb(ctx, "123.jpg")
res, err := handler.Thumb(ctx, file)
asserts.Error(err)
asserts.Empty(res.URL)
}
// 上下文错误
{
_, err := handler.Thumb(context.Background(), "123.jpg")
_, err := handler.Thumb(context.Background(), file)
asserts.Error(err)
}
}

View File

@@ -3,6 +3,7 @@ package remote
import (
"context"
"errors"
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem/driver"
"github.com/cloudreve/Cloudreve/v3/pkg/mocks/remoteclientmock"
"github.com/cloudreve/Cloudreve/v3/pkg/serializer"
"io"
@@ -373,14 +374,33 @@ func TestHandler_Thumb(t *testing.T) {
Type: "remote",
SecretKey: "test",
Server: "http://test.com",
OptionsSerialized: model.PolicyOption{
ThumbExts: []string{"txt"},
},
},
AuthInstance: auth.HMACAuth{},
}
file := &model.File{
Name: "1.txt",
SourceName: "1.txt",
}
ctx := context.Background()
asserts.NoError(cache.Set("setting_preview_timeout", "60", 0))
resp, err := handler.Thumb(ctx, "/1.txt")
asserts.NoError(err)
asserts.True(resp.Redirect)
// no error
{
resp, err := handler.Thumb(ctx, file)
asserts.NoError(err)
asserts.True(resp.Redirect)
}
// ext not support
{
file.Name = "1.jpg"
resp, err := handler.Thumb(ctx, file)
asserts.ErrorIs(err, driver.ErrorThumbNotSupported)
asserts.Nil(resp)
}
}
func TestHandler_Token(t *testing.T) {

View File

@@ -58,7 +58,6 @@ func TestFileSystem_AddFile(t *testing.T) {
asserts.NoError(err)
asserts.NoError(mock.ExpectationsWereMet())
asserts.Equal("/Uploads/1_sad.png", f.SourceName)
asserts.NotEmpty(f.PicInfo)
// 前置钩子执行失败
{
@@ -312,6 +311,19 @@ func TestFileSystem_deleteGroupedFile(t *testing.T) {
_, ok := cache.Get(UploadSessionCachePrefix + sessionID)
asserts.False(ok)
}
// 包含缩略图
{
files[0].MetadataSerialized = map[string]string{
model.ThumbSidecarMetadataKey: "1",
}
failed := fs.deleteGroupedFile(ctx, fs.GroupFileByPolicy(ctx, files))
asserts.Equal(map[uint][]string{
1: {},
2: {},
3: {},
}, failed)
}
}
func TestFileSystem_GetSource(t *testing.T) {

View File

@@ -360,7 +360,7 @@ func TestHookClearFileSize(t *testing.T) {
)
mock.ExpectBegin()
mock.ExpectExec("UPDATE(.+)files(.+)").
WithArgs(0, sqlmock.AnyArg(), 1, 10).
WithArgs("", 0, sqlmock.AnyArg(), 1, 10).
WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectExec("UPDATE(.+)users(.+)").
WithArgs(10, sqlmock.AnyArg()).
@@ -394,7 +394,7 @@ func TestHookUpdateSourceName(t *testing.T) {
}
ctx := context.WithValue(context.Background(), fsctx.FileModelCtx, originFile)
mock.ExpectBegin()
mock.ExpectExec("UPDATE(.+)").WithArgs("new.txt", sqlmock.AnyArg(), 1).WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectExec("UPDATE(.+)").WithArgs("", "new.txt", sqlmock.AnyArg(), 1).WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()
err := HookUpdateSourceName(ctx, fs, nil)
asserts.NoError(mock.ExpectationsWereMet())
@@ -429,7 +429,7 @@ func TestGenericAfterUpdate(t *testing.T) {
fs.Handler = handlerMock
mock.ExpectBegin()
mock.ExpectExec("UPDATE(.+)files(.+)").
WithArgs(10, sqlmock.AnyArg(), 1, 0).
WithArgs("", 10, sqlmock.AnyArg(), 1, 0).
WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectExec("UPDATE(.+)users(.+)").
WithArgs(10, sqlmock.AnyArg()).
@@ -462,7 +462,7 @@ func TestGenericAfterUpdate(t *testing.T) {
mock.ExpectBegin()
mock.ExpectExec("UPDATE(.+)").
WithArgs(10, sqlmock.AnyArg(), 1, 0).
WithArgs("", 10, sqlmock.AnyArg(), 1, 0).
WillReturnError(errors.New("error"))
mock.ExpectRollback()
@@ -473,27 +473,6 @@ func TestGenericAfterUpdate(t *testing.T) {
}
}
func TestHookGenerateThumb(t *testing.T) {
a := assert.New(t)
mockHandler := &FileHeaderMock{}
fs := &FileSystem{
User: &model.User{
Model: gorm.Model{ID: 1},
},
Handler: mockHandler,
Policy: &model.Policy{Type: "local"},
}
mockHandler.On("Delete", testMock.Anything, []string{"1.txt._thumb"}).Return([]string{}, nil)
a.NoError(HookGenerateThumb(context.Background(), fs, &fsctx.FileStream{
Model: &model.File{
SourceName: "1.txt",
},
}))
fs.Recycle()
mockHandler.AssertExpectations(t)
}
func TestSlaveAfterUpload(t *testing.T) {
asserts := assert.New(t)
conf.SystemConfig.Mode = "slave"
@@ -625,7 +604,7 @@ func TestHookChunkUploaded(t *testing.T) {
}
mock.ExpectBegin()
mock.ExpectExec("UPDATE(.+)files(.+)").WithArgs(20, sqlmock.AnyArg(), 1, 0).WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectExec("UPDATE(.+)files(.+)").WithArgs("", 20, sqlmock.AnyArg(), 1, 0).WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectExec("UPDATE(.+)users(.+)").
WithArgs(20, sqlmock.AnyArg()).
WillReturnResult(sqlmock.NewResult(1, 1))
@@ -646,7 +625,7 @@ func TestHookChunkUploadFailed(t *testing.T) {
}
mock.ExpectBegin()
mock.ExpectExec("UPDATE(.+)files(.+)").WithArgs(10, sqlmock.AnyArg(), 1, 0).WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectExec("UPDATE(.+)files(.+)").WithArgs("", 10, sqlmock.AnyArg(), 1, 0).WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectExec("UPDATE(.+)users(.+)").
WithArgs(10, sqlmock.AnyArg()).
WillReturnResult(sqlmock.NewResult(1, 1))

View File

@@ -28,9 +28,7 @@ func (fs *FileSystem) GetThumb(ctx context.Context, id uint) (*response.ContentR
// 根据 ID 查找文件
err := fs.resetFileIDIfNotExist(ctx, id)
if err != nil {
return &response.ContentResponse{
Redirect: false,
}, ErrObjectNotExist
return nil, ErrObjectNotExist
}
file := fs.FileTarget[0]
@@ -44,7 +42,7 @@ func (fs *FileSystem) GetThumb(ctx context.Context, id uint) (*response.ContentR
res, err := fs.Handler.Thumb(ctx, &file)
if errors.Is(err, driver.ErrorThumbNotExist) {
// Regenerate thumb if the thumb is not initialized yet
if generateErr := fs.GenerateThumbnail(ctx, &file); generateErr == nil {
if generateErr := fs.generateThumbnail(ctx, &file); generateErr == nil {
res, err = fs.Handler.Thumb(ctx, &file)
} else {
err = generateErr
@@ -69,7 +67,7 @@ func (fs *FileSystem) GetThumb(ctx context.Context, id uint) (*response.ContentR
)
} else {
// if not exist, generate and upload the sidecar thumb.
if err = fs.GenerateThumbnail(ctx, &file); err == nil {
if err = fs.generateThumbnail(ctx, &file); err == nil {
return fs.GetThumb(ctx, id)
}
}
@@ -119,8 +117,8 @@ func (pool *Pool) releaseWorker() {
<-pool.worker
}
// GenerateThumbnail generates thumb for given file, upload the thumb file back with given suffix
func (fs *FileSystem) GenerateThumbnail(ctx context.Context, file *model.File) error {
// generateThumbnail generates thumb for given file, upload the thumb file back with given suffix
func (fs *FileSystem) generateThumbnail(ctx context.Context, file *model.File) error {
// 新建上下文
newCtx, cancel := context.WithCancel(context.Background())
defer cancel()
@@ -164,13 +162,13 @@ func (fs *FileSystem) GenerateThumbnail(ctx context.Context, file *model.File) e
thumbFile, err := os.Open(thumbRes.Path)
if err != nil {
return fmt.Errorf("failed to open temp thumb %q: %w", thumbFile, err)
return fmt.Errorf("failed to open temp thumb %q: %w", thumbRes.Path, err)
}
defer thumbFile.Close()
fileInfo, err := thumbFile.Stat()
if err != nil {
return fmt.Errorf("failed to stat temp thumb %q: %w", thumbFile, err)
return fmt.Errorf("failed to stat temp thumb %q: %w", thumbRes.Path, err)
}
if err = fs.Handler.Put(newCtx, &fsctx.FileStream{
@@ -184,7 +182,7 @@ func (fs *FileSystem) GenerateThumbnail(ctx context.Context, file *model.File) e
}
if model.IsTrueVal(model.GetSettingByName("thumb_gc_after_gen")) {
util.Log().Debug("GenerateThumbnail runtime.GC")
util.Log().Debug("generateThumbnail runtime.GC")
runtime.GC()
}

View File

@@ -5,8 +5,11 @@ import (
"errors"
model "github.com/cloudreve/Cloudreve/v3/models"
"github.com/cloudreve/Cloudreve/v3/pkg/cache"
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem/driver"
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem/response"
"github.com/cloudreve/Cloudreve/v3/pkg/mocks/thumbmock"
"github.com/cloudreve/Cloudreve/v3/pkg/request"
"github.com/cloudreve/Cloudreve/v3/pkg/thumb"
testMock "github.com/stretchr/testify/mock"
"testing"
@@ -14,30 +17,104 @@ import (
)
func TestFileSystem_GetThumb(t *testing.T) {
asserts := assert.New(t)
a := assert.New(t)
fs := &FileSystem{User: &model.User{}}
// 非图像文件
// file not found
{
fs.SetTargetFile(&[]model.File{{}})
_, err := fs.GetThumb(context.Background(), 1)
asserts.Equal(err, ErrObjectNotExist)
mock.ExpectQuery("SELECT(.+)").WillReturnError(errors.New("error"))
res, err := fs.GetThumb(context.Background(), 1)
a.ErrorIs(err, ErrObjectNotExist)
a.Nil(res)
a.NoError(mock.ExpectationsWereMet())
}
// 成功
// thumb not exist
{
cache.Set("setting_thumb_width", "10", 0)
cache.Set("setting_thumb_height", "10", 0)
cache.Set("setting_preview_timeout", "50", 0)
testHandller2 := new(FileHeaderMock)
testHandller2.On("Thumb", testMock.Anything, "").Return(&response.ContentResponse{}, nil)
fs.CleanTargets()
fs.SetTargetFile(&[]model.File{{PicInfo: "1,1", Policy: model.Policy{Type: "mock"}}})
fs.SetTargetFile(&[]model.File{{
MetadataSerialized: map[string]string{
model.ThumbStatusMetadataKey: model.ThumbStatusNotAvailable,
},
Policy: model.Policy{Type: "mock"},
}})
fs.FileTarget[0].Policy.ID = 1
fs.Handler = testHandller2
res, err := fs.GetThumb(context.Background(), 1)
asserts.NoError(err)
asserts.EqualValues(50, res.MaxAge)
a.ErrorIs(err, ErrObjectNotExist)
a.Nil(res)
}
// thumb not initialized, also failed to generate
{
fs.CleanTargets()
fs.SetTargetFile(&[]model.File{{
Policy: model.Policy{Type: "mock"},
Size: 31457281,
}})
testHandller2 := new(FileHeaderMock)
testHandller2.On("Thumb", testMock.Anything, &fs.FileTarget[0]).Return(&response.ContentResponse{}, driver.ErrorThumbNotExist)
fs.Handler = testHandller2
fs.FileTarget[0].Policy.ID = 1
res, err := fs.GetThumb(context.Background(), 1)
a.Contains(err.Error(), "file too large")
a.Nil(res.Content)
}
// thumb not initialized, failed to get source
{
fs.CleanTargets()
fs.SetTargetFile(&[]model.File{{
Policy: model.Policy{Type: "mock"},
}})
testHandller2 := new(FileHeaderMock)
testHandller2.On("Thumb", testMock.Anything, &fs.FileTarget[0]).Return(&response.ContentResponse{}, driver.ErrorThumbNotExist)
testHandller2.On("Get", testMock.Anything, "").Return(MockRSC{}, errors.New("error"))
fs.Handler = testHandller2
fs.FileTarget[0].Policy.ID = 1
res, err := fs.GetThumb(context.Background(), 1)
a.Contains(err.Error(), "error")
a.Nil(res.Content)
}
// thumb not initialized, no available generators
{
thumb.Generators = []thumb.Generator{}
fs.CleanTargets()
fs.SetTargetFile(&[]model.File{{
Policy: model.Policy{Type: "local"},
}})
testHandller2 := new(FileHeaderMock)
testHandller2.On("Thumb", testMock.Anything, &fs.FileTarget[0]).Return(&response.ContentResponse{}, driver.ErrorThumbNotExist)
testHandller2.On("Get", testMock.Anything, "").Return(MockRSC{}, nil)
fs.Handler = testHandller2
fs.FileTarget[0].Policy.ID = 1
res, err := fs.GetThumb(context.Background(), 1)
a.ErrorIs(err, thumb.ErrNotAvailable)
a.Nil(res)
}
// thumb not initialized, thumb generated but cannot be open
{
mockGenerator := &thumbmock.GeneratorMock{}
thumb.Generators = []thumb.Generator{mockGenerator}
fs.CleanTargets()
fs.SetTargetFile(&[]model.File{{
Policy: model.Policy{Type: "mock"},
}})
cache.Set("setting_thumb_vips_enabled", "1", 0)
testHandller2 := new(FileHeaderMock)
testHandller2.On("Thumb", testMock.Anything, &fs.FileTarget[0]).Return(&response.ContentResponse{}, driver.ErrorThumbNotExist)
testHandller2.On("Get", testMock.Anything, "").Return(MockRSC{}, nil)
mockGenerator.On("Generate", testMock.Anything, testMock.Anything, testMock.Anything, testMock.Anything, testMock.Anything).
Return(&thumb.Result{Path: "not_exit_thumb"}, nil)
fs.Handler = testHandller2
fs.FileTarget[0].Policy.ID = 1
res, err := fs.GetThumb(context.Background(), 1)
a.Contains(err.Error(), "failed to open temp thumb")
a.Nil(res.Content)
testHandller2.AssertExpectations(t)
mockGenerator.AssertExpectations(t)
}
}
@@ -56,7 +133,7 @@ func TestFileSystem_GenerateThumbnail(t *testing.T) {
// 无法生成缩略图
{
fs.SetTargetFile(&[]model.File{{}})
fs.GenerateThumbnail(context.Background(), &model.File{})
fs.generateThumbnail(context.Background(), &model.File{})
}
// 无法获取文件数据
@@ -64,7 +141,7 @@ func TestFileSystem_GenerateThumbnail(t *testing.T) {
testHandller := new(FileHeaderMock)
testHandller.On("Get", testMock.Anything, "").Return(request.NopRSCloser{}, errors.New("error"))
fs.Handler = testHandller
fs.GenerateThumbnail(context.Background(), &model.File{Name: "test.png"})
fs.generateThumbnail(context.Background(), &model.File{Name: "test.png"})
testHandller.AssertExpectations(t)
}
}

View File

@@ -55,7 +55,7 @@ func (m FileHeaderMock) Delete(ctx context.Context, files []string) ([]string, e
return args.Get(0).([]string), args.Error(1)
}
func (m FileHeaderMock) Thumb(ctx context.Context, files string) (*response.ContentResponse, error) {
func (m FileHeaderMock) Thumb(ctx context.Context, files *model.File) (*response.ContentResponse, error) {
args := m.Called(ctx, files)
return args.Get(0).(*response.ContentResponse), args.Error(1)
}