mirror of
https://github.com/tw93/Mole.git
synced 2026-03-22 21:20:09 +00:00
- Add TestValidatePath covering Chinese, emoji, and special characters - Add TestValidatePathWithChineseAndSpecialChars for filesystem tests - Fix validatePath to detect .. components without rejecting valid paths Ensures paths with $, ;, :, emoji, Chinese chars are not rejected while still blocking path traversal attempts.
165 lines
4.6 KiB
Go
165 lines
4.6 KiB
Go
//go:build darwin
|
|
|
|
package main
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestTrashPathWithProgress(t *testing.T) {
|
|
skipIfFinderUnavailable(t)
|
|
|
|
parent := t.TempDir()
|
|
target := filepath.Join(parent, "target")
|
|
if err := os.MkdirAll(target, 0o755); err != nil {
|
|
t.Fatalf("create target: %v", err)
|
|
}
|
|
|
|
files := []string{
|
|
filepath.Join(target, "one.txt"),
|
|
filepath.Join(target, "two.txt"),
|
|
}
|
|
for _, f := range files {
|
|
if err := os.WriteFile(f, []byte("content"), 0o644); err != nil {
|
|
t.Fatalf("write %s: %v", f, err)
|
|
}
|
|
}
|
|
|
|
var counter int64
|
|
count, err := trashPathWithProgress(target, &counter)
|
|
if err != nil {
|
|
t.Fatalf("trashPathWithProgress returned error: %v", err)
|
|
}
|
|
if count != int64(len(files)) {
|
|
t.Fatalf("expected %d files trashed, got %d", len(files), count)
|
|
}
|
|
if _, err := os.Stat(target); !os.IsNotExist(err) {
|
|
t.Fatalf("expected target to be moved to Trash, stat err=%v", err)
|
|
}
|
|
}
|
|
|
|
func TestDeleteMultiplePathsCmdHandlesParentChild(t *testing.T) {
|
|
skipIfFinderUnavailable(t)
|
|
|
|
base := t.TempDir()
|
|
parent := filepath.Join(base, "parent")
|
|
child := filepath.Join(parent, "child")
|
|
|
|
// Structure: parent/fileA, parent/child/fileC.
|
|
if err := os.MkdirAll(child, 0o755); err != nil {
|
|
t.Fatalf("mkdir: %v", err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(parent, "fileA"), []byte("a"), 0o644); err != nil {
|
|
t.Fatalf("write fileA: %v", err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(child, "fileC"), []byte("c"), 0o644); err != nil {
|
|
t.Fatalf("write fileC: %v", err)
|
|
}
|
|
|
|
var counter int64
|
|
msg := deleteMultiplePathsCmd([]string{parent, child}, &counter)()
|
|
progress, ok := msg.(deleteProgressMsg)
|
|
if !ok {
|
|
t.Fatalf("expected deleteProgressMsg, got %T", msg)
|
|
}
|
|
if progress.err != nil {
|
|
t.Fatalf("unexpected error: %v", progress.err)
|
|
}
|
|
if progress.count != 2 {
|
|
t.Fatalf("expected 2 files trashed, got %d", progress.count)
|
|
}
|
|
if _, err := os.Stat(parent); !os.IsNotExist(err) {
|
|
t.Fatalf("expected parent to be moved to Trash, err=%v", err)
|
|
}
|
|
}
|
|
|
|
func TestMoveToTrashNonExistent(t *testing.T) {
|
|
err := moveToTrash("/nonexistent/path/that/does/not/exist")
|
|
if err == nil {
|
|
t.Fatal("expected error for non-existent path")
|
|
}
|
|
}
|
|
|
|
func TestValidatePath(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
path string
|
|
wantErr bool
|
|
}{
|
|
// 基本合法路径
|
|
{"absolute path", "/Users/test/file.txt", false},
|
|
{"path with spaces", "/Users/test/My Documents/file.txt", false},
|
|
{"root", "/", false},
|
|
|
|
// 中文路径
|
|
{"chinese path", "/Users/test/中文文件夹/文件.txt", false},
|
|
{"chinese mixed", "/Users/test/Downloads/报告2024.pdf", false},
|
|
|
|
// Emoji 路径
|
|
{"emoji path", "/Users/test/📁文件夹/📝笔记.txt", false},
|
|
{"emoji only", "/Users/test/🎉/🎊.txt", false},
|
|
|
|
// 特殊字符路径 (之前被错误拒绝的)
|
|
{"dollar sign", "/Users/test/$HOME/workspace", false},
|
|
{"semicolon", "/Users/test/project;v2", false},
|
|
{"colon", "/Users/test/project:2024", false},
|
|
{"ampersand", "/Users/test/R&D/project", false},
|
|
{"at sign", "/Users/test/user@domain", false},
|
|
{"hash", "/Users/test/project#123", false},
|
|
{"percent", "/Users/test/100% complete", false},
|
|
{"exclamation", "/Users/test/important!.txt", false},
|
|
{"single quote", "/Users/test/user's files", false},
|
|
{"equals", "/Users/test/key=value", false},
|
|
{"plus", "/Users/test/file+v2", false},
|
|
{"brackets", "/Users/test/[2024] report", false},
|
|
{"parentheses", "/Users/test/project (copy)", false},
|
|
{"comma", "/Users/test/file, backup", false},
|
|
|
|
// 非法路径
|
|
{"empty", "", true},
|
|
{"relative", "relative/path", true},
|
|
{"relative dot", "./file.txt", true},
|
|
{"null byte", "/Users/test\x00/file", true},
|
|
{"path traversal", "/Users/test/../../../etc", true},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := validatePath(tt.path)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("validatePath(%q) error = %v, wantErr %v", tt.path, err, tt.wantErr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestValidatePathWithChineseAndSpecialChars(t *testing.T) {
|
|
// 专门测试之前会导致兼容性回退的路径
|
|
parent := t.TempDir()
|
|
testCases := []struct {
|
|
name string
|
|
path string
|
|
}{
|
|
{"chinese", "中文文件夹"},
|
|
{"emoji", "📁 文档"},
|
|
{"mixed", "报告-2024_v2 (终稿) [已审核]"},
|
|
{"special", "Project$2024; Q1: R&D"},
|
|
{"complex", "用户@公司 100% 完成!"},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
fullPath := filepath.Join(parent, tc.path)
|
|
if err := os.MkdirAll(fullPath, 0o755); err != nil {
|
|
t.Fatalf("mkdir %q: %v", tc.path, err)
|
|
}
|
|
|
|
if err := validatePath(fullPath); err != nil {
|
|
t.Errorf("validatePath rejected valid path %q: %v", tc.path, err)
|
|
}
|
|
})
|
|
}
|
|
}
|