You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
498 lines
16 KiB
498 lines
16 KiB
package model
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"gorm.io/driver/mysql"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// setupFileTestDB 创建测试数据库(使用MySQL)
|
|
func setupFileTestDB(t *testing.T) *gorm.DB {
|
|
t.Helper()
|
|
|
|
// 使用 MySQL 进行测试
|
|
dsn := "root:dev123456@tcp(219.159.132.177:17173)/base?charset=utf8mb4&parseTime=true&loc=Local"
|
|
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
|
require.NoError(t, err)
|
|
|
|
err = db.AutoMigrate(&File{})
|
|
require.NoError(t, err)
|
|
|
|
// 清理所有测试数据(TRUNCATE)
|
|
db.Exec("SET FOREIGN_KEY_CHECKS = 0")
|
|
db.Exec("TRUNCATE TABLE file")
|
|
db.Exec("SET FOREIGN_KEY_CHECKS = 1")
|
|
|
|
return db
|
|
}
|
|
|
|
// createTestFile 创建测试文件
|
|
func createTestFile(t *testing.T, db *gorm.DB) *File {
|
|
t.Helper()
|
|
|
|
now := time.Now()
|
|
file := &File{
|
|
Name: "test-file.pdf",
|
|
Key: "uploads/2026/02/test-file.pdf",
|
|
Size: 1024000,
|
|
MimeType: "application/pdf",
|
|
Category: "document",
|
|
IsPublic: false,
|
|
UserId: 1,
|
|
StorageType: "local",
|
|
Status: 1,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
|
|
err := db.Create(file).Error
|
|
require.NoError(t, err)
|
|
|
|
return file
|
|
}
|
|
|
|
// TestFileInsert 测试插入文件
|
|
func TestFileInsert(t *testing.T) {
|
|
db := setupFileTestDB(t)
|
|
|
|
ctx := context.Background()
|
|
file := &File{
|
|
Name: "new-file.jpg",
|
|
Key: "uploads/2026/02/new-file.jpg",
|
|
Size: 2048000,
|
|
MimeType: "image/jpeg",
|
|
Category: "image",
|
|
IsPublic: true,
|
|
UserId: 1,
|
|
StorageType: "local",
|
|
Status: 1,
|
|
}
|
|
|
|
id, err := FileInsert(ctx, db, file)
|
|
|
|
require.NoError(t, err)
|
|
assert.Greater(t, id, int64(0))
|
|
assert.Equal(t, id, file.Id)
|
|
|
|
// 验证所有字段已保存
|
|
saved, err := FileFindOne(ctx, db, id)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "new-file.jpg", saved.Name)
|
|
assert.Equal(t, "uploads/2026/02/new-file.jpg", saved.Key)
|
|
assert.Equal(t, int64(2048000), saved.Size)
|
|
assert.Equal(t, "image/jpeg", saved.MimeType)
|
|
assert.Equal(t, "image", saved.Category)
|
|
assert.True(t, saved.IsPublic)
|
|
assert.Equal(t, int64(1), saved.UserId)
|
|
assert.Equal(t, "local", saved.StorageType)
|
|
assert.Equal(t, 1, saved.Status)
|
|
assert.NotZero(t, saved.CreatedAt)
|
|
assert.NotZero(t, saved.UpdatedAt)
|
|
}
|
|
|
|
// TestFileFindOne 测试根据ID查询文件
|
|
func TestFileFindOne(t *testing.T) {
|
|
db := setupFileTestDB(t)
|
|
|
|
// 创建测试文件
|
|
file := createTestFile(t, db)
|
|
ctx := context.Background()
|
|
|
|
// 查询文件
|
|
found, err := FileFindOne(ctx, db, file.Id)
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, found)
|
|
assert.Equal(t, file.Id, found.Id)
|
|
assert.Equal(t, "test-file.pdf", found.Name)
|
|
assert.Equal(t, "uploads/2026/02/test-file.pdf", found.Key)
|
|
assert.Equal(t, int64(1024000), found.Size)
|
|
assert.Equal(t, "application/pdf", found.MimeType)
|
|
assert.Equal(t, "document", found.Category)
|
|
assert.False(t, found.IsPublic)
|
|
assert.Equal(t, int64(1), found.UserId)
|
|
}
|
|
|
|
// TestFileFindOne_NotFound 测试查询不存在的文件
|
|
func TestFileFindOne_NotFound(t *testing.T) {
|
|
db := setupFileTestDB(t)
|
|
|
|
ctx := context.Background()
|
|
|
|
found, err := FileFindOne(ctx, db, 99999)
|
|
|
|
require.Error(t, err)
|
|
require.Nil(t, found)
|
|
assert.Equal(t, ErrNotFound, err)
|
|
}
|
|
|
|
// TestFileFindList_Pagination 测试分页查询
|
|
func TestFileFindList_Pagination(t *testing.T) {
|
|
db := setupFileTestDB(t)
|
|
ctx := context.Background()
|
|
|
|
// 创建5个测试文件
|
|
now := time.Now()
|
|
files := []File{
|
|
{Name: "file1.pdf", Key: "uploads/file1.pdf", Size: 1000, MimeType: "application/pdf", Category: "document", IsPublic: true, UserId: 1, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
{Name: "file2.pdf", Key: "uploads/file2.pdf", Size: 2000, MimeType: "application/pdf", Category: "document", IsPublic: true, UserId: 1, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
{Name: "file3.pdf", Key: "uploads/file3.pdf", Size: 3000, MimeType: "application/pdf", Category: "document", IsPublic: true, UserId: 1, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
{Name: "file4.pdf", Key: "uploads/file4.pdf", Size: 4000, MimeType: "application/pdf", Category: "document", IsPublic: true, UserId: 1, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
{Name: "file5.pdf", Key: "uploads/file5.pdf", Size: 5000, MimeType: "application/pdf", Category: "document", IsPublic: true, UserId: 1, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
}
|
|
|
|
for _, f := range files {
|
|
err := db.Create(&f).Error
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// 测试分页查询(第1页,每页2条)
|
|
list, total, err := FileFindList(ctx, db, 1, 2, "", "", "", 1, RoleAdmin)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(5), total)
|
|
assert.Len(t, list, 2)
|
|
}
|
|
|
|
// TestFileFindList_KeywordFilter 测试关键词筛选
|
|
func TestFileFindList_KeywordFilter(t *testing.T) {
|
|
db := setupFileTestDB(t)
|
|
ctx := context.Background()
|
|
|
|
// 创建不同名称的文件
|
|
now := time.Now()
|
|
files := []File{
|
|
{Name: "report-2026.pdf", Key: "uploads/report-2026.pdf", Size: 1000, MimeType: "application/pdf", Category: "document", IsPublic: true, UserId: 1, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
{Name: "invoice-january.pdf", Key: "uploads/invoice-january.pdf", Size: 2000, MimeType: "application/pdf", Category: "document", IsPublic: true, UserId: 1, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
{Name: "report-2025.pdf", Key: "uploads/report-2025.pdf", Size: 3000, MimeType: "application/pdf", Category: "document", IsPublic: true, UserId: 1, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
}
|
|
|
|
for _, f := range files {
|
|
err := db.Create(&f).Error
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// 搜索包含 "report" 的文件
|
|
list, total, err := FileFindList(ctx, db, 1, 10, "report", "", "", 1, RoleAdmin)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(2), total)
|
|
assert.Len(t, list, 2)
|
|
|
|
// 搜索包含 "invoice" 的文件
|
|
list, total, err = FileFindList(ctx, db, 1, 10, "invoice", "", "", 1, RoleAdmin)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(1), total)
|
|
assert.Len(t, list, 1)
|
|
assert.Equal(t, "invoice-january.pdf", list[0].Name)
|
|
}
|
|
|
|
// TestFileFindList_CategoryFilter 测试分类筛选
|
|
func TestFileFindList_CategoryFilter(t *testing.T) {
|
|
db := setupFileTestDB(t)
|
|
ctx := context.Background()
|
|
|
|
// 创建不同分类的文件
|
|
now := time.Now()
|
|
files := []File{
|
|
{Name: "photo1.jpg", Key: "uploads/photo1.jpg", Size: 1000, MimeType: "image/jpeg", Category: "image", IsPublic: true, UserId: 1, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
{Name: "photo2.jpg", Key: "uploads/photo2.jpg", Size: 2000, MimeType: "image/jpeg", Category: "image", IsPublic: true, UserId: 1, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
{Name: "report.pdf", Key: "uploads/report.pdf", Size: 3000, MimeType: "application/pdf", Category: "document", IsPublic: true, UserId: 1, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
{Name: "video.mp4", Key: "uploads/video.mp4", Size: 4000, MimeType: "video/mp4", Category: "video", IsPublic: true, UserId: 1, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
}
|
|
|
|
for _, f := range files {
|
|
err := db.Create(&f).Error
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// 筛选 image 分类
|
|
list, total, err := FileFindList(ctx, db, 1, 10, "", "image", "", 1, RoleAdmin)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(2), total)
|
|
assert.Len(t, list, 2)
|
|
|
|
// 筛选 document 分类
|
|
list, total, err = FileFindList(ctx, db, 1, 10, "", "document", "", 1, RoleAdmin)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(1), total)
|
|
assert.Len(t, list, 1)
|
|
assert.Equal(t, "report.pdf", list[0].Name)
|
|
|
|
// 筛选 video 分类
|
|
list, total, err = FileFindList(ctx, db, 1, 10, "", "video", "", 1, RoleAdmin)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(1), total)
|
|
assert.Len(t, list, 1)
|
|
assert.Equal(t, "video.mp4", list[0].Name)
|
|
}
|
|
|
|
// TestFileFindList_PermissionFilter 测试权限筛选
|
|
func TestFileFindList_PermissionFilter(t *testing.T) {
|
|
db := setupFileTestDB(t)
|
|
ctx := context.Background()
|
|
|
|
// 创建不同用户的文件(公开和私有)
|
|
now := time.Now()
|
|
files := []File{
|
|
// 用户1的私有文件
|
|
{Name: "user1-private.pdf", Key: "uploads/user1-private.pdf", Size: 1000, MimeType: "application/pdf", Category: "document", IsPublic: false, UserId: 1, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
// 用户1的公开文件
|
|
{Name: "user1-public.pdf", Key: "uploads/user1-public.pdf", Size: 2000, MimeType: "application/pdf", Category: "document", IsPublic: true, UserId: 1, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
// 用户2的私有文件
|
|
{Name: "user2-private.pdf", Key: "uploads/user2-private.pdf", Size: 3000, MimeType: "application/pdf", Category: "document", IsPublic: false, UserId: 2, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
// 用户2的公开文件
|
|
{Name: "user2-public.pdf", Key: "uploads/user2-public.pdf", Size: 4000, MimeType: "application/pdf", Category: "document", IsPublic: true, UserId: 2, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
}
|
|
|
|
for _, f := range files {
|
|
err := db.Create(&f).Error
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// 测试1:admin 角色可以看到所有文件
|
|
list, total, err := FileFindList(ctx, db, 1, 10, "", "", "", 1, RoleAdmin)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(4), total)
|
|
assert.Len(t, list, 4)
|
|
|
|
// 测试2:super_admin 角色也可以看到所有文件
|
|
list, total, err = FileFindList(ctx, db, 1, 10, "", "", "", 1, RoleSuperAdmin)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(4), total)
|
|
assert.Len(t, list, 4)
|
|
|
|
// 测试3:普通用户(user1)只能看到自己的文件 + 所有公开文件
|
|
list, total, err = FileFindList(ctx, db, 1, 10, "", "", "", 1, RoleUser)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(3), total) // user1的2个文件 + user2的1个公开文件
|
|
assert.Len(t, list, 3)
|
|
|
|
// 验证返回的文件:user1-private, user1-public, user2-public
|
|
fileNames := make(map[string]bool)
|
|
for _, f := range list {
|
|
fileNames[f.Name] = true
|
|
}
|
|
assert.True(t, fileNames["user1-private.pdf"])
|
|
assert.True(t, fileNames["user1-public.pdf"])
|
|
assert.True(t, fileNames["user2-public.pdf"])
|
|
assert.False(t, fileNames["user2-private.pdf"]) // 不应该包含
|
|
|
|
// 测试4:普通用户(user2)只能看到自己的文件 + 所有公开文件
|
|
list, total, err = FileFindList(ctx, db, 1, 10, "", "", "", 2, RoleUser)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(3), total) // user2的2个文件 + user1的1个公开文件
|
|
assert.Len(t, list, 3)
|
|
|
|
// 验证返回的文件:user2-private, user2-public, user1-public
|
|
fileNames = make(map[string]bool)
|
|
for _, f := range list {
|
|
fileNames[f.Name] = true
|
|
}
|
|
assert.True(t, fileNames["user2-private.pdf"])
|
|
assert.True(t, fileNames["user2-public.pdf"])
|
|
assert.True(t, fileNames["user1-public.pdf"])
|
|
assert.False(t, fileNames["user1-private.pdf"]) // 不应该包含
|
|
}
|
|
|
|
// TestFileUpdate 测试更新文件
|
|
func TestFileUpdate(t *testing.T) {
|
|
db := setupFileTestDB(t)
|
|
|
|
// 创建测试文件
|
|
file := createTestFile(t, db)
|
|
ctx := context.Background()
|
|
|
|
// 修改文件数据
|
|
file.Name = "updated-file.pdf"
|
|
file.Category = "report"
|
|
file.IsPublic = true
|
|
|
|
// 更新
|
|
err := FileUpdate(ctx, db, file)
|
|
|
|
require.NoError(t, err)
|
|
|
|
// 验证更新结果
|
|
updated, err := FileFindOne(ctx, db, file.Id)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "updated-file.pdf", updated.Name)
|
|
assert.Equal(t, "report", updated.Category)
|
|
assert.True(t, updated.IsPublic)
|
|
// 验证其他字段未改变
|
|
assert.Equal(t, "uploads/2026/02/test-file.pdf", updated.Key)
|
|
assert.Equal(t, int64(1024000), updated.Size)
|
|
}
|
|
|
|
// TestFileDelete 测试删除文件(软删除)
|
|
func TestFileDelete(t *testing.T) {
|
|
db := setupFileTestDB(t)
|
|
|
|
// 创建测试文件
|
|
file := createTestFile(t, db)
|
|
fileId := file.Id
|
|
ctx := context.Background()
|
|
|
|
// 删除文件
|
|
err := FileDelete(ctx, db, fileId)
|
|
|
|
require.NoError(t, err)
|
|
|
|
// 验证文件已被软删除(FileFindOne 应该返回 ErrNotFound,因为它过滤 status=1)
|
|
_, err = FileFindOne(ctx, db, fileId)
|
|
require.Error(t, err)
|
|
assert.Equal(t, ErrNotFound, err)
|
|
|
|
// 验证数据库中记录仍然存在但 status=0
|
|
var deletedFile File
|
|
err = db.WithContext(ctx).Where("id = ?", fileId).First(&deletedFile).Error
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 0, deletedFile.Status)
|
|
}
|
|
|
|
// TestFileFindList_EmptyResult 测试查询空列表
|
|
func TestFileFindList_EmptyResult(t *testing.T) {
|
|
db := setupFileTestDB(t)
|
|
ctx := context.Background()
|
|
|
|
list, total, err := FileFindList(ctx, db, 1, 10, "", "", "", 1, RoleAdmin)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(0), total)
|
|
assert.Empty(t, list)
|
|
}
|
|
|
|
// TestFileFindList_MimeTypeFilter 测试 MIME 类型筛选
|
|
func TestFileFindList_MimeTypeFilter(t *testing.T) {
|
|
db := setupFileTestDB(t)
|
|
ctx := context.Background()
|
|
|
|
// 创建不同 MIME 类型的文件
|
|
now := time.Now()
|
|
files := []File{
|
|
{Name: "photo1.jpg", Key: "uploads/photo1.jpg", Size: 1000, MimeType: "image/jpeg", Category: "image", IsPublic: true, UserId: 1, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
{Name: "photo2.png", Key: "uploads/photo2.png", Size: 2000, MimeType: "image/png", Category: "image", IsPublic: true, UserId: 1, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
{Name: "report.pdf", Key: "uploads/report.pdf", Size: 3000, MimeType: "application/pdf", Category: "document", IsPublic: true, UserId: 1, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
{Name: "video.mp4", Key: "uploads/video.mp4", Size: 4000, MimeType: "video/mp4", Category: "video", IsPublic: true, UserId: 1, StorageType: "local", Status: 1, CreatedAt: now, UpdatedAt: now},
|
|
}
|
|
|
|
for _, f := range files {
|
|
err := db.Create(&f).Error
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// 筛选 image/* 类型(前缀匹配)
|
|
list, total, err := FileFindList(ctx, db, 1, 10, "", "", "image", 1, RoleAdmin)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(2), total)
|
|
assert.Len(t, list, 2)
|
|
|
|
// 筛选 application/* 类型
|
|
list, total, err = FileFindList(ctx, db, 1, 10, "", "", "application", 1, RoleAdmin)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(1), total)
|
|
assert.Len(t, list, 1)
|
|
assert.Equal(t, "report.pdf", list[0].Name)
|
|
}
|
|
|
|
// BenchmarkFileInsert 性能测试
|
|
func BenchmarkFileInsert(b *testing.B) {
|
|
db := setupFileTestDB(&testing.T{})
|
|
ctx := context.Background()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
file := &File{
|
|
Name: "benchmark-file.pdf",
|
|
Key: "uploads/benchmark-file.pdf",
|
|
Size: 1024000,
|
|
MimeType: "application/pdf",
|
|
Category: "document",
|
|
IsPublic: false,
|
|
UserId: 1,
|
|
StorageType: "local",
|
|
Status: 1,
|
|
}
|
|
_, _ = FileInsert(ctx, db, file)
|
|
}
|
|
}
|
|
|
|
// BenchmarkFileFindOne 性能测试
|
|
func BenchmarkFileFindOne(b *testing.B) {
|
|
db := setupFileTestDB(&testing.T{})
|
|
ctx := context.Background()
|
|
|
|
// 创建测试文件
|
|
now := time.Now()
|
|
file := &File{
|
|
Name: "benchmark-file.pdf",
|
|
Key: "uploads/benchmark-file.pdf",
|
|
Size: 1024000,
|
|
MimeType: "application/pdf",
|
|
Category: "document",
|
|
IsPublic: false,
|
|
UserId: 1,
|
|
StorageType: "local",
|
|
Status: 1,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
|
|
err := db.Create(file).Error
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_, _ = FileFindOne(ctx, db, file.Id)
|
|
}
|
|
}
|
|
|
|
// BenchmarkFileFindList 性能测试
|
|
func BenchmarkFileFindList(b *testing.B) {
|
|
db := setupFileTestDB(&testing.T{})
|
|
ctx := context.Background()
|
|
|
|
// 创建100个测试文件
|
|
now := time.Now()
|
|
for i := 0; i < 100; i++ {
|
|
file := &File{
|
|
Name: "benchmark-file.pdf",
|
|
Key: "uploads/benchmark-file.pdf",
|
|
Size: 1024000,
|
|
MimeType: "application/pdf",
|
|
Category: "document",
|
|
IsPublic: true,
|
|
UserId: 1,
|
|
StorageType: "local",
|
|
Status: 1,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
err := db.Create(file).Error
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_, _, _ = FileFindList(ctx, db, 1, 10, "", "", "", 1, RoleAdmin)
|
|
}
|
|
}
|
|
|