file-system/internal/common/sanitize_test.go
向宁 b5df6445e5 refactor: commit all pending file_system changes
- Restructure handlers into file_commands/file_queries/file_handlers
- Add gRPC auth client, JWT middleware, rate limiting, request ID
- Add common utilities: logger, sanitizer, s3_errors
- Add unit tests for config, mediator, auth, request_id, sanitize
- Add proto definitions and generated code
- Remove old web UI pages
- Add .dockerignore and .env.example
2026-05-17 22:20:02 +08:00

109 lines
2.9 KiB
Go

package common
import (
"strings"
"testing"
)
// ---------------------------------------------------------------------------
// SanitizeObjectKey
// ---------------------------------------------------------------------------
func TestSanitizeObjectKey_ValidInput(t *testing.T) {
keys := []string{"folder/file.txt", "file.csv", "a/b/c/d.json"}
for _, key := range keys {
if err := SanitizeObjectKey(key); err != nil {
t.Errorf("expected nil for key %q, got error: %v", key, err)
}
}
}
func TestSanitizeObjectKey_PathTraversal(t *testing.T) {
cases := []struct {
name string
key string
}{
{"double dot", "../etc/passwd"},
{"double dot middle", "a/../b"},
{"double slash", "folder//file.txt"},
{"leading slash", "/absolute/path"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
err := SanitizeObjectKey(tc.key)
if err == nil {
t.Errorf("expected error for key %q, got nil", tc.key)
}
})
}
}
// ---------------------------------------------------------------------------
// SanitizeBucketName
// ---------------------------------------------------------------------------
func TestSanitizeBucketName_Valid(t *testing.T) {
names := []string{"my-bucket", "bucket123", "a1b", "my.bucket.name"}
for _, name := range names {
if err := SanitizeBucketName(name); err != nil {
t.Errorf("expected nil for bucket %q, got error: %v", name, err)
}
}
}
func TestSanitizeBucketName_Invalid(t *testing.T) {
cases := []struct {
name string
input string
}{
{"uppercase", "MyBucket"},
{"too short", "ab"},
{"starts with hyphen", "-bucket"},
{"starts with dot", ".bucket"},
{"contains underscore", "my_bucket"},
{"empty", ""},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
err := SanitizeBucketName(tc.input)
if err == nil {
t.Errorf("expected error for bucket %q, got nil", tc.input)
}
})
}
}
func TestSanitizeBucketName_TooLong(t *testing.T) {
longName := strings.Repeat("a", 64)
if err := SanitizeBucketName(longName); err == nil {
t.Error("expected error for bucket name > 63 chars, got nil")
}
}
// ---------------------------------------------------------------------------
// SanitizeFilename
// ---------------------------------------------------------------------------
func TestSanitizeFilename_RemovesCRLF(t *testing.T) {
input := "file\r\nname.txt"
got := SanitizeFilename(input)
if strings.Contains(got, "\r") || strings.Contains(got, "\n") {
t.Errorf("expected \\r and \\n removed, got %q", got)
}
}
func TestSanitizeFilename_EscapesQuotes(t *testing.T) {
input := `some"file.txt`
got := SanitizeFilename(input)
if strings.Contains(got, `"`) && !strings.Contains(got, `\"`) {
t.Errorf("expected quotes escaped, got %q", got)
}
}
func TestSanitizeFilename_CleanInput(t *testing.T) {
input := "clean-file.txt"
if got := SanitizeFilename(input); got != input {
t.Errorf("expected %q, got %q", input, got)
}
}