axe/internal/handlers/photos_test.go

85 lines
3.0 KiB
Go
Raw Normal View History

2026-10-18 19:07:25 +00:00
package handlers
import (
"strings"
"testing"
)
// TestSniffImage — белый список форматов по сигнатуре: только фото.
func TestSniffImage(t *testing.T) {
jpeg := []byte{0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10}
png := []byte{0x89, 'P', 'N', 'G', 0x0D, 0x0A, 0x1A, 0x0A, 0x00}
webp := []byte("RIFF\x24\x00\x00\x00WEBPVP8 ")
cases := []struct {
name string
data []byte
contentType string
ext string
}{
{"jpeg", jpeg, "image/jpeg", "jpg"},
{"png", png, "image/png", "png"},
{"webp", webp, "image/webp", "webp"},
{"gif is not photo", []byte("GIF89a"), "", ""},
{"bmp is not photo", []byte("BM\x00\x00"), "", ""},
{"svg text", []byte(`<svg xmlns="http://www.w3.org/2000/svg"></svg>`), "", ""},
{"empty", nil, "", ""},
{"truncated jpeg", []byte{0xFF, 0xD8}, "", ""},
{"riff but not webp", []byte("RIFF\x00\x00\x00\x00WAVEfmt "), "", ""},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
contentType, ext, ok := sniffImage(tc.data)
if tc.contentType == "" {
if ok {
t.Errorf("sniff = (%q, %q, true), want reject", contentType, ext)
}
return
}
if !ok || contentType != tc.contentType || ext != tc.ext {
t.Errorf("sniff = (%q, %q, %v), want (%q, %q, true)",
contentType, ext, ok, tc.contentType, tc.ext)
}
})
}
}
// TestPhotoName — имя файла из multipart: без путей, управляющих
// символов и без бесконечных строк (оно уходит в журнал событий).
func TestPhotoName(t *testing.T) {
cases := []struct {
in string
want string
}{
{"photo.jpg", "photo.jpg"},
{`C:\Users\me\photo.jpg`, "photo.jpg"}, // имя с Windows-путём
{"../../etc/passwd", "passwd"}, // path traversal вырезается
{"a\x00b\x1fc.png", "abc.png"}, // управляющие символы
{"", ""}, // имя не передали
{".", ""}, // path.Base(".") = "."
{strings.Repeat("я", 150) + ".jpg", strings.Repeat("я", 100)}, // обрезка по рунам
}
for _, tc := range cases {
if got := photoName(tc.in); got != tc.want {
t.Errorf("photoName(%q) = %q, want %q", tc.in, got, tc.want)
}
}
}
// TestNewPhotoHandlerDefaults — лимиты из env могли быть нулём
// (не заданы): хендлер обязан подставить дефолты, а не считать с нулём.
func TestNewPhotoHandlerDefaults(t *testing.T) {
h := NewPhotoHandler(nil, nil, nil, nil, 0, -1)
if h.maxBytes != photoDefaultMaxBytes {
t.Errorf("maxBytes = %d, want %d", h.maxBytes, photoDefaultMaxBytes)
}
if h.maxPer != photoDefaultMaxPer {
t.Errorf("maxPer = %d, want %d", h.maxPer, photoDefaultMaxPer)
}
custom := NewPhotoHandler(nil, nil, nil, nil, 4096, 3)
if custom.maxBytes != 4096 || custom.maxPer != 3 {
t.Errorf("custom limits = %d/%d, want 4096/3", custom.maxBytes, custom.maxPer)
}
}