//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") } }