Minor adjustments to profile handler imports and main router configuration. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
267 lines
8.7 KiB
Go
267 lines
8.7 KiB
Go
//go:build test
|
|
// +build test
|
|
|
|
package images
|
|
|
|
import (
|
|
"bytes"
|
|
"testing"
|
|
)
|
|
|
|
// TestValidateImageBytes_JPEG verifies that JPEG magic bytes (FF D8 FF) are detected.
|
|
func TestValidateImageBytes_JPEG(t *testing.T) {
|
|
data := []byte{0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01}
|
|
ext, err := ValidateImageBytes(data)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if ext != ".jpg" {
|
|
t.Errorf("expected .jpg, got %q", ext)
|
|
}
|
|
}
|
|
|
|
// TestValidateImageBytes_PNG verifies that PNG magic bytes are detected.
|
|
func TestValidateImageBytes_PNG(t *testing.T) {
|
|
data := []byte{0x89, 'P', 'N', 'G', '\r', '\n', 0x1a, '\n', 0x00, 0x00, 0x00, 0x0d}
|
|
ext, err := ValidateImageBytes(data)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if ext != ".png" {
|
|
t.Errorf("expected .png, got %q", ext)
|
|
}
|
|
}
|
|
|
|
// TestValidateImageBytes_GIF87a verifies GIF87a magic bytes are detected.
|
|
func TestValidateImageBytes_GIF87a(t *testing.T) {
|
|
data := []byte{'G', 'I', 'F', '8', '7', 'a', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
|
ext, err := ValidateImageBytes(data)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if ext != ".gif" {
|
|
t.Errorf("expected .gif, got %q", ext)
|
|
}
|
|
}
|
|
|
|
// TestValidateImageBytes_GIF89a verifies GIF89a magic bytes are detected.
|
|
func TestValidateImageBytes_GIF89a(t *testing.T) {
|
|
data := []byte{'G', 'I', 'F', '8', '9', 'a', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
|
ext, err := ValidateImageBytes(data)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if ext != ".gif" {
|
|
t.Errorf("expected .gif, got %q", ext)
|
|
}
|
|
}
|
|
|
|
// TestValidateImageBytes_WebP verifies RIFF...WEBP magic bytes are detected.
|
|
func TestValidateImageBytes_WebP(t *testing.T) {
|
|
data := []byte{'R', 'I', 'F', 'F', 0x00, 0x00, 0x00, 0x00, 'W', 'E', 'B', 'P'}
|
|
ext, err := ValidateImageBytes(data)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if ext != ".webp" {
|
|
t.Errorf("expected .webp, got %q", ext)
|
|
}
|
|
}
|
|
|
|
// TestValidateImageBytes_AVIF verifies ftypavif magic bytes are detected.
|
|
func TestValidateImageBytes_AVIF(t *testing.T) {
|
|
data := []byte{0x00, 0x00, 0x00, 0x20, 'f', 't', 'y', 'p', 'a', 'v', 'i', 'f'}
|
|
ext, err := ValidateImageBytes(data)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if ext != ".avif" {
|
|
t.Errorf("expected .avif, got %q", ext)
|
|
}
|
|
}
|
|
|
|
// TestValidateImageBytes_AVIS verifies ftypavis (AVIF image sequence) magic bytes are detected.
|
|
func TestValidateImageBytes_AVIS(t *testing.T) {
|
|
data := []byte{0x00, 0x00, 0x00, 0x20, 'f', 't', 'y', 'p', 'a', 'v', 'i', 's'}
|
|
ext, err := ValidateImageBytes(data)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if ext != ".avif" {
|
|
t.Errorf("expected .avif, got %q", ext)
|
|
}
|
|
}
|
|
|
|
// TestValidateImageBytes_JXL verifies ftypjxl magic bytes are detected.
|
|
func TestValidateImageBytes_JXL(t *testing.T) {
|
|
data := []byte{0x00, 0x00, 0x00, 0x0c, 'f', 't', 'y', 'p', 'j', 'x', 'l', ' '}
|
|
ext, err := ValidateImageBytes(data)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if ext != ".jxl" {
|
|
t.Errorf("expected .jxl, got %q", ext)
|
|
}
|
|
}
|
|
|
|
// TestValidateImageBytes_TooSmall verifies that files smaller than 12 bytes are rejected.
|
|
func TestValidateImageBytes_TooSmall(t *testing.T) {
|
|
data := []byte{0xff, 0xd8, 0xff}
|
|
_, err := ValidateImageBytes(data)
|
|
if err == nil {
|
|
t.Fatal("expected error for too-small file, got nil")
|
|
}
|
|
}
|
|
|
|
// TestValidateImageBytes_UnknownFormat verifies that unrecognized magic bytes return an error.
|
|
func TestValidateImageBytes_UnknownFormat(t *testing.T) {
|
|
data := []byte("this is not an image file at all!!")
|
|
_, err := ValidateImageBytes(data)
|
|
if err == nil {
|
|
t.Fatal("expected error for unknown format, got nil")
|
|
}
|
|
}
|
|
|
|
// TestValidateImageBytes_Exact12Bytes verifies the boundary condition of exactly 12 bytes.
|
|
func TestValidateImageBytes_Exact12Bytes(t *testing.T) {
|
|
// Valid JPEG header truncated to exactly 12 bytes (should still match 3-byte magic)
|
|
data := []byte{0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01}
|
|
ext, err := ValidateImageBytes(data)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if ext != ".jpg" {
|
|
t.Errorf("expected .jpg, got %q", ext)
|
|
}
|
|
}
|
|
|
|
// TestValidateImageBytes_WebPNotRIFF verifies that WEBP without RIFF prefix is rejected.
|
|
func TestValidateImageBytes_WebPNotRIFF(t *testing.T) {
|
|
data := []byte{'W', 'E', 'B', 'P', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
|
_, err := ValidateImageBytes(data)
|
|
if err == nil {
|
|
t.Fatal("expected error for WEBP without RIFF prefix, got nil")
|
|
}
|
|
}
|
|
|
|
// TestValidateImageBytes_AVIFWrongBrand verifies that ftyp with wrong brand is rejected.
|
|
func TestValidateImageBytes_AVIFWrongBrand(t *testing.T) {
|
|
// ftyp with "mp41" brand (not avif/avis)
|
|
data := []byte{0x00, 0x00, 0x00, 0x20, 'f', 't', 'y', 'p', 'm', 'p', '4', '1'}
|
|
_, err := ValidateImageBytes(data)
|
|
if err == nil {
|
|
t.Fatal("expected error for non-AVIF ftyp, got nil")
|
|
}
|
|
}
|
|
|
|
// TestValidateImageBytes_Empty verifies that empty input is rejected.
|
|
func TestValidateImageBytes_Empty(t *testing.T) {
|
|
data := []byte{}
|
|
_, err := ValidateImageBytes(data)
|
|
if err == nil {
|
|
t.Fatal("expected error for empty input, got nil")
|
|
}
|
|
}
|
|
|
|
// TestValidateImageBytes_AllSupportedFormats verifies every supported format returns a non-empty extension.
|
|
func TestValidateImageBytes_AllSupportedFormats(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
data []byte
|
|
wantExt string
|
|
wantErr bool
|
|
}{
|
|
{"JPEG", []byte{0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01}, ".jpg", false},
|
|
{"PNG", []byte{0x89, 'P', 'N', 'G', '\r', '\n', 0x1a, '\n', 0, 0, 0, 0}, ".png", false},
|
|
{"GIF87a", []byte{'G', 'I', 'F', '8', '7', 'a', 0, 0, 0, 0, 0, 0}, ".gif", false},
|
|
{"GIF89a", []byte{'G', 'I', 'F', '8', '9', 'a', 0, 0, 0, 0, 0, 0}, ".gif", false},
|
|
{"WebP", []byte{'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'E', 'B', 'P'}, ".webp", false},
|
|
{"AVIF", []byte{0, 0, 0, 0x20, 'f', 't', 'y', 'p', 'a', 'v', 'i', 'f'}, ".avif", false},
|
|
{"AVIS", []byte{0, 0, 0, 0x20, 'f', 't', 'y', 'p', 'a', 'v', 'i', 's'}, ".avif", false},
|
|
{"JXL", []byte{0, 0, 0, 0x0c, 'f', 't', 'y', 'p', 'j', 'x', 'l', ' '}, ".jxl", false},
|
|
{"Random", []byte("not-an-image-file!"), "", true},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
ext, err := ValidateImageBytes(tc.data)
|
|
if tc.wantErr {
|
|
if err == nil {
|
|
t.Errorf("expected error, got nil")
|
|
}
|
|
} else {
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if ext != tc.wantExt {
|
|
t.Errorf("expected %q, got %q", tc.wantExt, ext)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestValidateImageBytes_NoFalsePositiveJPEG verifies that data starting with FF D8 but not FF D8 FF is rejected.
|
|
func TestValidateImageBytes_NoFalsePositiveJPEG(t *testing.T) {
|
|
data := []byte{0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
|
_, err := ValidateImageBytes(data)
|
|
if err == nil {
|
|
t.Fatal("expected error for non-JPEG starting with FF D8, got nil")
|
|
}
|
|
}
|
|
|
|
// TestValidateImageBytes_PartialMagic verifies that partial magic bytes (e.g., only first 2 bytes of PNG) are rejected.
|
|
func TestValidateImageBytes_PartialMagic(t *testing.T) {
|
|
// Only first 2 bytes of PNG signature
|
|
data := []byte{0x89, 'P', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
|
_, err := ValidateImageBytes(data)
|
|
if err == nil {
|
|
t.Fatal("expected error for partial PNG magic, got nil")
|
|
}
|
|
}
|
|
|
|
// BenchmarkValidateImageBytes measures validation throughput.
|
|
func BenchmarkValidateImageBytes(b *testing.B) {
|
|
data := []byte{0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01}
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_, _ = ValidateImageBytes(data)
|
|
}
|
|
}
|
|
|
|
// BenchmarkValidateImageBytes_AVIF measures AVIF detection throughput.
|
|
func BenchmarkValidateImageBytes_AVIF(b *testing.B) {
|
|
data := []byte{0x00, 0x00, 0x00, 0x20, 'f', 't', 'y', 'p', 'a', 'v', 'i', 'f'}
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_, _ = ValidateImageBytes(data)
|
|
}
|
|
}
|
|
|
|
// BenchmarkValidateImageBytes_WebP measures WebP detection throughput.
|
|
func BenchmarkValidateImageBytes_WebP(b *testing.B) {
|
|
data := []byte{'R', 'I', 'F', 'F', 0x00, 0x00, 0x00, 0x00, 'W', 'E', 'B', 'P'}
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_, _ = ValidateImageBytes(data)
|
|
}
|
|
}
|
|
|
|
// BenchmarkValidateImageBytes_JXL measures JXL detection throughput.
|
|
func BenchmarkValidateImageBytes_JXL(b *testing.B) {
|
|
data := []byte{0x00, 0x00, 0x00, 0x0c, 'f', 't', 'y', 'p', 'j', 'x', 'l', ' '}
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_, _ = ValidateImageBytes(data)
|
|
}
|
|
}
|
|
|
|
// TestValidateImageBytes_11Bytes verifies that 11-byte files (just under the 12-byte minimum) are rejected.
|
|
func TestValidateImageBytes_11Bytes(t *testing.T) {
|
|
data := bytes.Repeat([]byte{0x00}, 11)
|
|
_, err := ValidateImageBytes(data)
|
|
if err == nil {
|
|
t.Fatal("expected error for 11-byte file, got nil")
|
|
}
|
|
}
|