Test: file compress / download
This commit is contained in:
parent
03dcd9a9e0
commit
ca07a94d41
15 changed files with 367 additions and 2 deletions
|
@ -1,6 +1,7 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"github.com/HFO4/cloudreve/pkg/util"
|
||||
"github.com/jinzhu/gorm"
|
||||
"path"
|
||||
|
@ -25,6 +26,11 @@ type File struct {
|
|||
Position string `gorm:"-"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
// 注册缓存用到的复杂结构
|
||||
gob.Register(File{})
|
||||
}
|
||||
|
||||
// Create 创建文件记录
|
||||
func (file *File) Create() (uint, error) {
|
||||
if err := DB.Create(file).Error; err != nil {
|
||||
|
|
|
@ -64,6 +64,8 @@ func TestFolder_GetChildFiles(t *testing.T) {
|
|||
Model: gorm.Model{
|
||||
ID: 1,
|
||||
},
|
||||
Position: "/123",
|
||||
Name: "456",
|
||||
}
|
||||
|
||||
// 找不到
|
||||
|
@ -78,6 +80,7 @@ func TestFolder_GetChildFiles(t *testing.T) {
|
|||
files, err = folder.GetChildFiles()
|
||||
asserts.NoError(err)
|
||||
asserts.Len(files, 2)
|
||||
asserts.Equal("/123/456", files[0].Position)
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
|
||||
}
|
||||
|
|
|
@ -73,6 +73,8 @@ func TestFolder_GetChildFolder(t *testing.T) {
|
|||
Model: gorm.Model{
|
||||
ID: 1,
|
||||
},
|
||||
Position: "/123",
|
||||
Name: "456",
|
||||
}
|
||||
|
||||
// 找不到
|
||||
|
@ -87,6 +89,7 @@ func TestFolder_GetChildFolder(t *testing.T) {
|
|||
files, err = folder.GetChildFolder()
|
||||
asserts.NoError(err)
|
||||
asserts.Len(files, 2)
|
||||
asserts.Equal("/123/456", files[0].Position)
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,9 @@ func addDefaultPolicy() {
|
|||
DirNameRule: "uploads/{uid}/{path}",
|
||||
FileNameRule: "{uid}_{randomkey8}_{originname}",
|
||||
IsOriginLinkEnable: false,
|
||||
OptionsSerialized: PolicyOption{
|
||||
FileType: []string{},
|
||||
},
|
||||
}
|
||||
if err := DB.Create(&defaultPolicy).Error; err != nil {
|
||||
util.Log().Panic("无法创建初始存储策略, %s", err)
|
||||
|
@ -76,7 +79,7 @@ func addDefaultPolicy() {
|
|||
|
||||
func addDefaultSettings() {
|
||||
defaultSettings := []Setting{
|
||||
{Name: "siteURL", Value: `http://lite.aoaoao.me/`, Type: "basic"},
|
||||
{Name: "siteURL", Value: ``, Type: "basic"},
|
||||
{Name: "siteName", Value: `Cloudreve`, Type: "basic"},
|
||||
{Name: "siteStatus", Value: `open`, Type: "basic"},
|
||||
{Name: "regStatus", Value: `0`, Type: "register"},
|
||||
|
|
|
@ -2,6 +2,7 @@ package auth
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
model "github.com/HFO4/cloudreve/models"
|
||||
"github.com/HFO4/cloudreve/pkg/util"
|
||||
|
@ -9,6 +10,7 @@ import (
|
|||
"github.com/jinzhu/gorm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var mock sqlmock.Sqlmock
|
||||
|
@ -64,6 +66,16 @@ func TestHMACAuth_Check(t *testing.T) {
|
|||
sign := auth.Sign("content", 1)
|
||||
asserts.Error(auth.Check("content", sign+":"))
|
||||
}
|
||||
|
||||
// 过期日期格式错误
|
||||
{
|
||||
asserts.Error(auth.Check("content", "ErrAuthFailed:ErrAuthFailed"))
|
||||
}
|
||||
|
||||
// 签名有误
|
||||
{
|
||||
asserts.Error(auth.Check("content", fmt.Sprintf("sign:%d", time.Now().Unix()+10)))
|
||||
}
|
||||
}
|
||||
|
||||
func TestInit(t *testing.T) {
|
||||
|
|
9
pkg/cache/driver_test.go
vendored
9
pkg/cache/driver_test.go
vendored
|
@ -23,6 +23,15 @@ func TestGet(t *testing.T) {
|
|||
asserts.False(ok)
|
||||
}
|
||||
|
||||
func TestDeletes(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
asserts.NoError(Set("123", "321", -1))
|
||||
err := Deletes([]string{"123"}, "")
|
||||
asserts.NoError(err)
|
||||
_, exist := Get("123")
|
||||
asserts.False(exist)
|
||||
}
|
||||
|
||||
func TestGetSettings(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
asserts.NoError(Set("test_1", "1", -1))
|
||||
|
|
59
pkg/filesystem/archive_test.go
Normal file
59
pkg/filesystem/archive_test.go
Normal file
|
@ -0,0 +1,59 @@
|
|||
package filesystem
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
model "github.com/HFO4/cloudreve/models"
|
||||
"github.com/HFO4/cloudreve/pkg/cache"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFileSystem_Compress(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
ctx := context.Background()
|
||||
fs := FileSystem{
|
||||
User: &model.User{Model: gorm.Model{ID: 1}},
|
||||
}
|
||||
|
||||
// 成功
|
||||
{
|
||||
// 查找压缩父目录
|
||||
mock.ExpectQuery("SELECT(.+)folders(.+)").
|
||||
WithArgs(1, 1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(1, "parent"))
|
||||
// 查找顶级待压缩文件
|
||||
mock.ExpectQuery("SELECT(.+)files(.+)").
|
||||
WithArgs(1, 1).
|
||||
WillReturnRows(
|
||||
sqlmock.NewRows(
|
||||
[]string{"id", "name", "source_name", "policy_id"}).
|
||||
AddRow(1, "1.txt", "tests/file1.txt", 1),
|
||||
)
|
||||
asserts.NoError(cache.Set("setting_temp_path", "tests", -1))
|
||||
// 查找父目录子文件
|
||||
mock.ExpectQuery("SELECT(.+)files(.+)").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "name", "source_name", "policy_id"}))
|
||||
// 查找子目录
|
||||
mock.ExpectQuery("SELECT(.+)folders(.+)").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(2, "sub"))
|
||||
// 查找子目录子文件
|
||||
mock.ExpectQuery("SELECT(.+)files(.+)").
|
||||
WithArgs(2).
|
||||
WillReturnRows(
|
||||
sqlmock.NewRows([]string{"id", "name", "source_name", "policy_id"}).
|
||||
AddRow(2, "2.txt", "tests/file2.txt", 1),
|
||||
)
|
||||
// 查找上传策略
|
||||
asserts.NoError(cache.Set("policy_1", model.Policy{Type: "local"}, -1))
|
||||
|
||||
zipFile, err := fs.Compress(ctx, []uint{1}, []uint{1})
|
||||
asserts.NoError(err)
|
||||
asserts.NotEmpty(zipFile)
|
||||
asserts.Contains(zipFile, "archive_")
|
||||
asserts.Contains(zipFile, "tests")
|
||||
}
|
||||
}
|
|
@ -208,7 +208,7 @@ func (fs *FileSystem) GetDownloadURL(ctx context.Context, path string) (string,
|
|||
ttl,
|
||||
)
|
||||
if err != nil {
|
||||
return "", serializer.NewError(serializer.CodeNotSet, "无法获取下载地址", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
return source, nil
|
||||
|
|
|
@ -380,3 +380,111 @@ func TestFileSystem_GetSource(t *testing.T) {
|
|||
fs.CleanTargets()
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileSystem_GetDownloadURL(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
ctx := context.Background()
|
||||
fs := FileSystem{
|
||||
User: &model.User{Model: gorm.Model{ID: 1}},
|
||||
}
|
||||
auth.General = auth.HMACAuth{SecretKey: []byte("123")}
|
||||
|
||||
// 正常
|
||||
{
|
||||
err := cache.Deletes([]string{"siteURL"}, "setting_")
|
||||
err = cache.Deletes([]string{"35"}, "policy_")
|
||||
err = cache.Deletes([]string{"download_timeout"}, "setting_")
|
||||
asserts.NoError(err)
|
||||
// 查找文件
|
||||
mock.ExpectQuery("SELECT(.+)").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1))
|
||||
mock.ExpectQuery("SELECT(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "policy_id"}).AddRow(1, "1.txt", 1))
|
||||
// 查找上传策略
|
||||
mock.ExpectQuery("SELECT(.+)").
|
||||
WillReturnRows(
|
||||
sqlmock.NewRows([]string{"id", "type", "is_origin_link_enable"}).
|
||||
AddRow(35, "local", true),
|
||||
)
|
||||
// 相关设置
|
||||
mock.ExpectQuery("SELECT(.+)").WithArgs("siteURL").WillReturnRows(sqlmock.NewRows([]string{"id", "value"}).AddRow(1, "https://cloudreve.org"))
|
||||
mock.ExpectQuery("SELECT(.+)").WithArgs("download_timeout").WillReturnRows(sqlmock.NewRows([]string{"id", "value"}).AddRow(1, "20"))
|
||||
|
||||
downloadURL, err := fs.GetDownloadURL(ctx, "/1.txt")
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
asserts.NoError(err)
|
||||
asserts.NotEmpty(downloadURL)
|
||||
fs.CleanTargets()
|
||||
}
|
||||
|
||||
// 文件不存在
|
||||
{
|
||||
err := cache.Deletes([]string{"siteURL"}, "setting_")
|
||||
err = cache.Deletes([]string{"35"}, "policy_")
|
||||
err = cache.Deletes([]string{"download_timeout"}, "setting_")
|
||||
asserts.NoError(err)
|
||||
// 查找文件
|
||||
mock.ExpectQuery("SELECT(.+)").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1))
|
||||
mock.ExpectQuery("SELECT(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "policy_id"}))
|
||||
|
||||
downloadURL, err := fs.GetDownloadURL(ctx, "/1.txt")
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
asserts.Error(err)
|
||||
asserts.Empty(downloadURL)
|
||||
fs.CleanTargets()
|
||||
}
|
||||
|
||||
// 未知存储策略
|
||||
{
|
||||
err := cache.Deletes([]string{"siteURL"}, "setting_")
|
||||
err = cache.Deletes([]string{"35"}, "policy_")
|
||||
err = cache.Deletes([]string{"download_timeout"}, "setting_")
|
||||
asserts.NoError(err)
|
||||
// 查找文件
|
||||
mock.ExpectQuery("SELECT(.+)").
|
||||
WithArgs(1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1))
|
||||
mock.ExpectQuery("SELECT(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "policy_id"}).AddRow(1, "1.txt", 1))
|
||||
// 查找上传策略
|
||||
mock.ExpectQuery("SELECT(.+)").
|
||||
WillReturnRows(
|
||||
sqlmock.NewRows([]string{"id", "type", "is_origin_link_enable"}).
|
||||
AddRow(35, "unknown", true),
|
||||
)
|
||||
|
||||
downloadURL, err := fs.GetDownloadURL(ctx, "/1.txt")
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
asserts.Error(err)
|
||||
asserts.Empty(downloadURL)
|
||||
fs.CleanTargets()
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileSystem_GetPhysicalFileContent(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
ctx := context.Background()
|
||||
fs := FileSystem{
|
||||
User: &model.User{},
|
||||
}
|
||||
|
||||
// 文件不存在
|
||||
{
|
||||
rs, err := fs.GetPhysicalFileContent(ctx, "not_exist.txt")
|
||||
asserts.Error(err)
|
||||
asserts.Nil(rs)
|
||||
}
|
||||
|
||||
// 成功
|
||||
{
|
||||
testFile, err := os.Create("GetPhysicalFileContent.txt")
|
||||
asserts.NoError(err)
|
||||
asserts.NoError(testFile.Close())
|
||||
|
||||
rs, err := fs.GetPhysicalFileContent(ctx, "GetPhysicalFileContent.txt")
|
||||
asserts.NoError(err)
|
||||
asserts.NoError(rs.Close())
|
||||
asserts.NotNil(rs)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,3 +151,36 @@ func TestHandler_Source(t *testing.T) {
|
|||
asserts.Empty(sourceURL)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandler_GetDownloadURL(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
handler := Handler{}
|
||||
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)
|
||||
baseURL, err := url.Parse("https://cloudreve.org")
|
||||
asserts.NoError(err)
|
||||
downloadURL, err := handler.GetDownloadURL(ctx, "", *baseURL, 10)
|
||||
asserts.NoError(err)
|
||||
asserts.Contains(downloadURL, "sign=")
|
||||
asserts.Contains(downloadURL, "https://cloudreve.org")
|
||||
}
|
||||
|
||||
// 无法获取上下文
|
||||
{
|
||||
baseURL, err := url.Parse("https://cloudreve.org")
|
||||
asserts.NoError(err)
|
||||
downloadURL, err := handler.GetDownloadURL(ctx, "", *baseURL, 10)
|
||||
asserts.Error(err)
|
||||
asserts.Empty(downloadURL)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -473,3 +473,111 @@ func TestFileSystem_Move(t *testing.T) {
|
|||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileSystem_Rename(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
fs := &FileSystem{User: &model.User{
|
||||
Model: gorm.Model{
|
||||
ID: 1,
|
||||
},
|
||||
}}
|
||||
ctx := context.Background()
|
||||
|
||||
// 重命名文件 成功
|
||||
{
|
||||
mock.ExpectQuery("SELECT(.+)files(.+)").
|
||||
WithArgs(10, 1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(10, "old.text"))
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectExec("UPDATE(.+)files(.+)").
|
||||
WithArgs("new.txt", sqlmock.AnyArg(), 10).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectCommit()
|
||||
err := fs.Rename(ctx, []uint{}, []uint{10}, "new.txt")
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
asserts.NoError(err)
|
||||
}
|
||||
|
||||
// 重命名文件 不存在
|
||||
{
|
||||
mock.ExpectQuery("SELECT(.+)files(.+)").
|
||||
WithArgs(10, 1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "name"}))
|
||||
err := fs.Rename(ctx, []uint{}, []uint{10}, "new.txt")
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
asserts.Error(err)
|
||||
asserts.Equal(ErrPathNotExist, err)
|
||||
}
|
||||
|
||||
// 重命名文件 失败
|
||||
{
|
||||
mock.ExpectQuery("SELECT(.+)files(.+)").
|
||||
WithArgs(10, 1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(10, "old.text"))
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectExec("UPDATE(.+)files(.+)").
|
||||
WithArgs("new.txt", sqlmock.AnyArg(), 10).
|
||||
WillReturnError(errors.New("error"))
|
||||
mock.ExpectRollback()
|
||||
err := fs.Rename(ctx, []uint{}, []uint{10}, "new.txt")
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
asserts.Error(err)
|
||||
asserts.Equal(ErrFileExisted, err)
|
||||
}
|
||||
|
||||
// 重命名目录 成功
|
||||
{
|
||||
mock.ExpectQuery("SELECT(.+)folders(.+)").
|
||||
WithArgs(10, 1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(10, "old"))
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectExec("UPDATE(.+)folders(.+)").
|
||||
WithArgs("new", sqlmock.AnyArg(), 10).
|
||||
WillReturnResult(sqlmock.NewResult(1, 1))
|
||||
mock.ExpectCommit()
|
||||
err := fs.Rename(ctx, []uint{10}, []uint{}, "new")
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
asserts.NoError(err)
|
||||
}
|
||||
|
||||
// 重命名目录 不存在
|
||||
{
|
||||
mock.ExpectQuery("SELECT(.+)folders(.+)").
|
||||
WithArgs(10, 1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "name"}))
|
||||
err := fs.Rename(ctx, []uint{10}, []uint{}, "new")
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
asserts.Error(err)
|
||||
asserts.Equal(ErrPathNotExist, err)
|
||||
}
|
||||
|
||||
// 重命名目录 失败
|
||||
{
|
||||
mock.ExpectQuery("SELECT(.+)folders(.+)").
|
||||
WithArgs(10, 1).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(10, "old"))
|
||||
mock.ExpectBegin()
|
||||
mock.ExpectExec("UPDATE(.+)folders(.+)").
|
||||
WithArgs("new", sqlmock.AnyArg(), 10).
|
||||
WillReturnError(errors.New("error"))
|
||||
mock.ExpectRollback()
|
||||
err := fs.Rename(ctx, []uint{10}, []uint{}, "new")
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
asserts.Error(err)
|
||||
asserts.Equal(ErrFileExisted, err)
|
||||
}
|
||||
|
||||
// 未选中任何对象
|
||||
{
|
||||
err := fs.Rename(ctx, []uint{}, []uint{}, "new")
|
||||
asserts.Error(err)
|
||||
asserts.Equal(ErrPathNotExist, err)
|
||||
}
|
||||
|
||||
// 新名字不合法
|
||||
{
|
||||
err := fs.Rename(ctx, []uint{10}, []uint{}, "ne/w")
|
||||
asserts.Error(err)
|
||||
asserts.Equal(ErrIllegalObjectName, err)
|
||||
}
|
||||
}
|
||||
|
|
0
pkg/filesystem/tests/file1.txt
Normal file
0
pkg/filesystem/tests/file1.txt
Normal file
0
pkg/filesystem/tests/file2.txt
Normal file
0
pkg/filesystem/tests/file2.txt
Normal file
|
@ -137,6 +137,25 @@ func Thumb(c *gin.Context) {
|
|||
|
||||
}
|
||||
|
||||
// RedirectToDownload 创建下载会话并重定向至下载地址
|
||||
func RedirectToDownload(c *gin.Context) {
|
||||
// 创建上下文
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
var service explorer.FileDownloadCreateService
|
||||
if err := c.ShouldBindUri(&service); err == nil {
|
||||
res := service.CreateDownloadSession(ctx, c)
|
||||
if res.Code == 0 {
|
||||
c.Redirect(301, res.Data.(string))
|
||||
return
|
||||
}
|
||||
c.JSON(200, res)
|
||||
} else {
|
||||
c.JSON(200, ErrorResponse(err))
|
||||
}
|
||||
}
|
||||
|
||||
// CreateDownloadSession 创建文件下载会话
|
||||
func CreateDownloadSession(c *gin.Context) {
|
||||
// 创建上下文
|
||||
|
|
|
@ -106,6 +106,8 @@ func InitRouter() *gin.Engine {
|
|||
file.POST("upload", controllers.FileUploadStream)
|
||||
// 创建文件下载会话
|
||||
file.PUT("download/*path", controllers.CreateDownloadSession)
|
||||
// 创建文件下载并重定向到下载地址
|
||||
file.GET("redirect/*path", controllers.RedirectToDownload)
|
||||
// 获取缩略图
|
||||
file.GET("thumb/:id", controllers.Thumb)
|
||||
// 取得文件外链
|
||||
|
|
Loading…
Add table
Reference in a new issue