package safepath import ( "errors" "path/filepath" "testing" ) func TestValidateRelative(t *testing.T) { valid := []string{ "JsonParser.exe", "bin/JsonParser.exe", "工具/解析器.exe", ".config/settings.json", "name..txt", "folder with spaces/read me.txt", } for _, value := range valid { t.Run("valid_"+value, func(t *testing.T) { if err := ValidateRelative(value); err != nil { t.Fatalf("ValidateRelative(%q) error = %v", value, err) } }) } invalid := []string{ "", ".", "..", "../escape.exe", "a/../escape.exe", "./App.exe", "a//App.exe", "a/", "/App.exe", "//server/share/App.exe", `C:/App.exe`, `C:App.exe`, `bin\App.exe`, "bad\x00name.exe", "bad\nname.exe", "badname.exe", `bad"name.exe`, "bad|name.exe", "bad?name.exe", "bad*name.exe", "folder./App.exe", "folder /App.exe", " App.exe", "folder/ App.exe", "App.exe.", "App.exe ", "CON", "con.txt", "PRN.json", "AUX", "NUL.bin", "NUL .bin", "COM1", "com9.log", "LPT1", "lpt9.txt", "COM¹", "LPT³.log", "CLOCK$", "CONIN$", "CONOUT$", } for _, value := range invalid { t.Run("invalid_"+value, func(t *testing.T) { err := ValidateRelative(value) if !errors.Is(err, ErrInvalidRelativePath) { t.Fatalf( "ValidateRelative(%q) error = %v, want %v", value, err, ErrInvalidRelativePath, ) } }) } } func TestValidateWorkingDirectory(t *testing.T) { for _, value := range []string{".", "bin", "资源/运行目录"} { if err := ValidateWorkingDirectory(value); err != nil { t.Fatalf("ValidateWorkingDirectory(%q) error = %v", value, err) } } for _, value := range []string{"", "..", "bin.", "NUL"} { if err := ValidateWorkingDirectory(value); !errors.Is(err, ErrInvalidRelativePath) { t.Fatalf( "ValidateWorkingDirectory(%q) error = %v, want %v", value, err, ErrInvalidRelativePath, ) } } } func TestCollisionKeyUsesUnicodeSimpleFold(t *testing.T) { tests := [][2]string{ {"App.EXE", "app.exe"}, {"K.exe", "K.exe"}, {"Σ.txt", "ς.txt"}, } for _, values := range tests { if CollisionKey(values[0]) != CollisionKey(values[1]) { t.Fatalf( "CollisionKey(%q) != CollisionKey(%q)", values[0], values[1], ) } } } func TestJoinUnder(t *testing.T) { root := filepath.Join(t.TempDir(), "staging") target, err := JoinUnder(root, "bin/App.exe") if err != nil { t.Fatalf("JoinUnder() error = %v", err) } want := filepath.Join(root, "bin", "App.exe") if target != want { t.Fatalf("JoinUnder() = %q, want %q", target, want) } for _, value := range []string{"../escape.exe", ".. /escape.exe", "/escape.exe"} { _, err := JoinUnder(root, value) if !errors.Is(err, ErrInvalidRelativePath) && !errors.Is(err, ErrOutsideRoot) { t.Fatalf("JoinUnder(%q) error = %v", value, err) } } }