lolly/internal/mimeutil/detect_test.go
xfy 4d66dd562f test(app,mimeutil): 添加应用和 MIME 检测测试
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-21 08:12:34 +08:00

199 lines
4.8 KiB
Go

package mimeutil
import (
"sync"
"testing"
)
// TestDetectContentType 测试 MIME 类型检测
func TestDetectContentType(t *testing.T) {
tests := []struct {
filePath string
want string
}{
// 标准库已知类型 (验证回退)
{"test.html", "text/html; charset=utf-8"},
{"test.css", "text/css; charset=utf-8"},
{"test.js", "text/javascript; charset=utf-8"},
{"test.json", "application/json"},
{"test.mjs", "text/javascript; charset=utf-8"}, // Go 1.26.2+ 已支持
// 包本地补充类型 - 缺失
{"test.eot", "application/vnd.ms-fontobject"},
{"test.webmanifest", "application/manifest+json"},
{"test.map", "application/json"},
// 包本地覆盖类型 - Go 返回错误类型
{"test.otf", "font/otf"}, // Go 返回 OpenDocument 公式模板
{"test.webm", "video/webm"}, // Go 返回 audio/webm
// 大小写处理 - 验证 strings.ToLower
{"test.EOT", "application/vnd.ms-fontobject"}, // 不在 Go 表中
{"test.WEBMANIFEST", "application/manifest+json"},
{"test.JPG", "image/jpeg"}, // Go 已知,也处理大小写
// 未知类型
{"test.unknown", ""},
}
for _, tt := range tests {
t.Run(tt.filePath, func(t *testing.T) {
got := DetectContentType(tt.filePath)
if got != tt.want {
t.Errorf("DetectContentType(%q) = %q, want %q", tt.filePath, got, tt.want)
}
})
}
}
// TestAddTypes 测试自定义 MIME 类型添加
func TestAddTypes(t *testing.T) {
tests := []struct {
name string
types map[string]string
filePath string
want string
}{
{
name: "添加新扩展名",
types: map[string]string{".xyz": "application/x-xyz"},
filePath: "test.xyz",
want: "application/x-xyz",
},
{
name: "覆盖已有映射",
types: map[string]string{".otf": "application/x-font-otf"},
filePath: "test.otf",
want: "application/x-font-otf",
},
{
name: "大写扩展名自动转小写",
types: map[string]string{".ABC": "application/x-abc"},
filePath: "test.abc",
want: "application/x-abc",
},
{
name: "多个映射同时添加",
types: map[string]string{".foo": "application/x-foo", ".bar": "application/x-bar"},
filePath: "test.foo",
want: "application/x-foo",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// 保存原始值以便恢复
original := make(map[string]string)
for ext := range tt.types {
original[ext] = mimeOverrides[ext]
}
AddTypes(tt.types)
got := DetectContentType(tt.filePath)
if got != tt.want {
t.Errorf("AddTypes: DetectContentType(%q) = %q, want %q", tt.filePath, got, tt.want)
}
// 恢复原始值
mimeMutex.Lock()
for ext, orig := range original {
if orig == "" {
delete(mimeOverrides, ext)
} else {
mimeOverrides[ext] = orig
}
}
mimeMutex.Unlock()
})
}
}
// TestSetDefaultType 测试设置默认 MIME 类型
func TestSetDefaultType(t *testing.T) {
// 保存原始默认值
original := GetDefaultType()
tests := []struct {
name string
want string
}{
{"设置为 text/plain", "text/plain"},
{"设置为 application/json", "application/json"},
{"设置为空字符串", ""},
{"恢复默认值", "application/octet-stream"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
SetDefaultType(tt.want)
got := GetDefaultType()
if got != tt.want {
t.Errorf("SetDefaultType(%q): GetDefaultType() = %q, want %q", tt.want, got, tt.want)
}
})
}
// 恢复原始值
SetDefaultType(original)
}
// TestGetDefaultType 测试获取默认 MIME 类型
func TestGetDefaultType(t *testing.T) {
// 保存原始默认值
original := GetDefaultType()
// 验证默认值
if original != "application/octet-stream" {
t.Errorf("GetDefaultType() = %q, want %q", original, "application/octet-stream")
}
// 测试设置后获取
SetDefaultType("text/plain")
if got := GetDefaultType(); got != "text/plain" {
t.Errorf("GetDefaultType() = %q, want %q", got, "text/plain")
}
// 恢复原始值
SetDefaultType(original)
}
// TestConcurrentAccess 测试并发访问安全性
func TestConcurrentAccess(t *testing.T) {
var wg sync.WaitGroup
numGoroutines := 100
// 并发调用 DetectContentType
wg.Add(numGoroutines)
for i := 0; i < numGoroutines; i++ {
go func() {
defer wg.Done()
DetectContentType("test.html")
}()
}
// 并发调用 AddTypes
wg.Add(numGoroutines)
for i := 0; i < numGoroutines; i++ {
go func(i int) {
defer wg.Done()
AddTypes(map[string]string{".test": "application/x-test"})
}(i)
}
// 并发调用 SetDefaultType 和 GetDefaultType
wg.Add(numGoroutines)
for i := 0; i < numGoroutines; i++ {
go func() {
defer wg.Done()
SetDefaultType("text/plain")
_ = GetDefaultType()
}()
}
wg.Wait()
// 恢复默认值
SetDefaultType("application/octet-stream")
}