// Package handler 提供 HTTP 请求处理功能。
package handler
import (
"os"
"path/filepath"
"testing"
"time"
"github.com/valyala/fasthttp"
)
func TestGenerateAutoIndex_HTML(t *testing.T) {
// 创建临时目录
tmpDir, err := os.MkdirTemp("", "autoindex_test")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpDir)
// 创建测试文件和目录
if err := os.WriteFile(filepath.Join(tmpDir, "file1.txt"), []byte("content1"), 0o644); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(tmpDir, "file2.html"), []byte("content2"), 0o644); err != nil {
t.Fatal(err)
}
if err := os.Mkdir(filepath.Join(tmpDir, "subdir"), 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(tmpDir, ".hidden"), []byte("hidden"), 0o644); err != nil {
t.Fatal(err)
}
// 测试 HTML 格式
ctx := &fasthttp.RequestCtx{}
ctx.Request.SetRequestURI("/test/")
config := AutoIndexConfig{
Format: "html",
Localtime: false,
ExactSize: false,
}
if !GenerateAutoIndex(ctx, tmpDir, "/test/", config) {
t.Fatal("GenerateAutoIndex returned false")
}
if ct := string(ctx.Response.Header.ContentType()); ct != "text/html; charset=utf-8" {
t.Errorf("Content-Type = %s, want text/html; charset=utf-8", ct)
}
body := string(ctx.Response.Body())
// 检查包含文件名
if !containsAll(body, "file1.txt", "file2.html", "subdir") {
t.Errorf("HTML body missing expected files: %s", body)
}
// 检查隐藏文件不显示
if containsAll(body, ".hidden") {
t.Errorf("HTML body should not contain hidden file: %s", body)
}
// 检查目录有斜杠后缀
if !containsAll(body, "subdir/") {
t.Errorf("HTML body directory should have / suffix: %s", body)
}
}
func TestGenerateAutoIndex_JSON(t *testing.T) {
// 创建临时目录
tmpDir, err := os.MkdirTemp("", "autoindex_test")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpDir)
// 创建测试文件
if err := os.WriteFile(filepath.Join(tmpDir, "test.json"), []byte("{}"), 0o644); err != nil {
t.Fatal(err)
}
// 测试 JSON 格式
ctx := &fasthttp.RequestCtx{}
ctx.Request.SetRequestURI("/api/")
config := AutoIndexConfig{
Format: "json",
}
if !GenerateAutoIndex(ctx, tmpDir, "/api/", config) {
t.Fatal("GenerateAutoIndex returned false")
}
if ct := string(ctx.Response.Header.ContentType()); ct != "application/json" {
t.Errorf("Content-Type = %s, want application/json", ct)
}
body := string(ctx.Response.Body())
// 检查 JSON 格式
if !containsAll(body, `"name"`, `"type"`, `"mtime"`, "test.json") {
t.Errorf("JSON body missing expected fields: %s", body)
}
}
func TestGenerateAutoIndex_XML(t *testing.T) {
// 创建临时目录
tmpDir, err := os.MkdirTemp("", "autoindex_test")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpDir)
// 创建测试文件
if err := os.WriteFile(filepath.Join(tmpDir, "data.xml"), []byte(""), 0o644); err != nil {
t.Fatal(err)
}
// 测试 XML 格式
ctx := &fasthttp.RequestCtx{}
ctx.Request.SetRequestURI("/xml/")
config := AutoIndexConfig{
Format: "xml",
}
if !GenerateAutoIndex(ctx, tmpDir, "/xml/", config) {
t.Fatal("GenerateAutoIndex returned false")
}
if ct := string(ctx.Response.Header.ContentType()); ct != "text/xml; charset=utf-8" {
t.Errorf("Content-Type = %s, want text/xml; charset=utf-8", ct)
}
body := string(ctx.Response.Body())
// 检查 XML 格式
if !containsAll(body, ` zFileIdx || dirIdx > mFileIdx {
t.Errorf("Directories should come first: dirIdx=%d, zFileIdx=%d, mFileIdx=%d", dirIdx, zFileIdx, mFileIdx)
}
}
func TestGenerateAutoIndex_SizeFormatting(t *testing.T) {
// 创建临时目录
tmpDir, err := os.MkdirTemp("", "autoindex_test")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpDir)
// 创建不同大小的文件
smallFile := filepath.Join(tmpDir, "small.txt")
if err := os.WriteFile(smallFile, make([]byte, 100), 0o644); err != nil {
t.Fatal(err)
}
// 测试人类可读格式
ctx := &fasthttp.RequestCtx{}
config := AutoIndexConfig{
Format: "html",
ExactSize: false,
}
if !GenerateAutoIndex(ctx, tmpDir, "/", config) {
t.Fatal("GenerateAutoIndex returned false")
}
body := string(ctx.Response.Body())
if !containsAll(body, "small.txt") {
t.Errorf("Missing file in output: %s", body)
}
}
func TestFormatSize(t *testing.T) {
tests := []struct {
size int64
expected string
}{
{0, "0"},
{100, "100"},
{1024, "1.0K"},
{1536, "1.5K"},
{1048576, "1.0M"},
{1572864, "1.5M"},
{1073741824, "1.0G"},
{1610612736, "1.5G"},
}
for _, tt := range tests {
result := formatSize(tt.size)
if result != tt.expected {
t.Errorf("formatSize(%d) = %s, want %s", tt.size, result, tt.expected)
}
}
}
func TestEscapeHTML(t *testing.T) {
tests := []struct {
input string
expected string
}{
{"normal", "normal"},
{"