package uploads import ( "bytes" "image" "image/color" "image/jpeg" "image/png" "strings" "testing" ) // makePNG and makeJPEG produce a tiny valid image for the round-trip tests. func makePNG(t *testing.T) []byte { t.Helper() img := image.NewRGBA(image.Rect(0, 0, 4, 4)) img.Set(0, 0, color.RGBA{34, 197, 94, 255}) var b bytes.Buffer if err := png.Encode(&b, img); err != nil { t.Fatalf("encode png: %v", err) } return b.Bytes() } func makeJPEG(t *testing.T) []byte { t.Helper() img := image.NewRGBA(image.Rect(0, 0, 4, 4)) img.Set(0, 0, color.RGBA{34, 197, 94, 255}) var b bytes.Buffer if err := jpeg.Encode(&b, img, &jpeg.Options{Quality: 80}); err != nil { t.Fatalf("encode jpeg: %v", err) } return b.Bytes() } func TestDecodeAndReencode_PNG(t *testing.T) { out, format, err := DecodeAndReencode(makePNG(t)) if err != nil { t.Fatalf("decode png: %v", err) } if format != FormatPNG { t.Errorf("format: got %q want png", format) } // Output must be valid PNG (round-trip decode). if _, _, err := image.Decode(bytes.NewReader(out)); err != nil { t.Errorf("re-encoded png is not valid: %v", err) } } func TestDecodeAndReencode_JPEG(t *testing.T) { out, format, err := DecodeAndReencode(makeJPEG(t)) if err != nil { t.Fatalf("decode jpeg: %v", err) } if format != FormatJPEG { t.Errorf("format: got %q want jpeg", format) } if _, _, err := image.Decode(bytes.NewReader(out)); err != nil { t.Errorf("re-encoded jpeg is not valid: %v", err) } } func TestDecodeAndReencode_RejectsNonImage(t *testing.T) { _, _, err := DecodeAndReencode([]byte("hello, world")) if err == nil { t.Fatal("expected an error decoding a non-image payload") } if !strings.Contains(err.Error(), "not a recognised image") { t.Errorf("error: got %q want 'not a recognised image'", err) } } func TestDecodeAndReencode_RejectsTooLarge(t *testing.T) { big := make([]byte, MaxUploadBytes+1) _, _, err := DecodeAndReencode(big) if err == nil || !strings.Contains(err.Error(), "exceeds") { t.Errorf("expected size-limit error, got %v", err) } } func TestLocalFSStore_FilePath_RejectsTraversal(t *testing.T) { s := &LocalFSStore{Dir: "/tmp/x", PublicBase: "http://localhost/up"} cases := []string{"../etc/passwd", "a/b.png", "..", ".env"} for _, in := range cases { if _, err := s.FilePath(in); err == nil { t.Errorf("FilePath(%q) should have refused", in) } } // A bare random filename should be accepted. if _, err := s.FilePath("ok.png"); err != nil { t.Errorf("FilePath(ok.png) should have accepted: %v", err) } }