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

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)
}
}