From 9bf353dd591f3459f549b00112774bdda421fc69 Mon Sep 17 00:00:00 2001 From: Laura Date: Tue, 12 Aug 2025 16:32:34 +0200 Subject: [PATCH] better tests --- .gitignore | 6 +- go.mod | 4 + go.sum | 2 + integration/example.jpeg | Bin 0 -> 22643 bytes {test => integration/images}/image.avif | Bin {test => integration/images}/image.bmp | Bin {test => integration/images}/image.cur | Bin {test => integration/images}/image.ff | Bin {test => integration/images}/image.gif | Bin {test => integration/images}/image.heic | Bin {test => integration/images}/image.heif | Bin {test => integration/images}/image.ico | Bin .../images/image.jpeg | Bin {test => integration/images}/image.jxl | Bin {test => integration/images}/image.pcx | Bin {test => integration/images}/image.png | Bin {test => integration/images}/image.pnm | 0 {test => integration/images}/image.psd | Bin {test => integration/images}/image.qoi | Bin {test => integration/images}/image.svg | 0 {test => integration/images}/image.tga | Bin {test => integration/images}/image.tif | Bin {test => integration/images}/image.tiff | Bin {test => integration/images}/image.webp | Bin {test => integration/images}/image.xbm | 0 integration/integration_test.go | 155 ++++++++++++++++++ internal/codec/detect.go | 8 +- 27 files changed, 168 insertions(+), 7 deletions(-) create mode 100644 integration/example.jpeg rename {test => integration/images}/image.avif (100%) rename {test => integration/images}/image.bmp (100%) rename {test => integration/images}/image.cur (100%) rename {test => integration/images}/image.ff (100%) rename {test => integration/images}/image.gif (100%) rename {test => integration/images}/image.heic (100%) rename {test => integration/images}/image.heif (100%) rename {test => integration/images}/image.ico (100%) rename test/image.jpg => integration/images/image.jpeg (100%) rename {test => integration/images}/image.jxl (100%) rename {test => integration/images}/image.pcx (100%) rename {test => integration/images}/image.png (100%) rename {test => integration/images}/image.pnm (100%) rename {test => integration/images}/image.psd (100%) rename {test => integration/images}/image.qoi (100%) rename {test => integration/images}/image.svg (100%) rename {test => integration/images}/image.tga (100%) rename {test => integration/images}/image.tif (100%) rename {test => integration/images}/image.tiff (100%) rename {test => integration/images}/image.webp (100%) rename {test => integration/images}/image.xbm (100%) create mode 100644 integration/integration_test.go diff --git a/.gitignore b/.gitignore index ccd315c..beffbd4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -bin -example.* test.* -*.exe +encoded.* +decoded.* +ffwebp.exe ffwebp \ No newline at end of file diff --git a/go.mod b/go.mod index 9354e14..87b68cd 100644 --- a/go.mod +++ b/go.mod @@ -21,15 +21,19 @@ require ( github.com/spakin/netpbm v1.3.2 github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef + github.com/stretchr/testify v1.10.0 github.com/xyproto/xbm v1.0.0 golang.org/x/image v0.30.0 ) require ( + github.com/davecgh/go-spew v1.1.1 // indirect github.com/ebitengine/purego v0.8.4 // indirect github.com/gopherjs/gopherjs v1.17.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/sergeymakinen/go-bmp v1.0.0 // indirect github.com/tetratelabs/wazero v1.9.0 // indirect golang.org/x/net v0.43.0 // indirect golang.org/x/text v0.28.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index e0aa853..ec1c106 100644 --- a/go.sum +++ b/go.sum @@ -56,5 +56,7 @@ golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/integration/example.jpeg b/integration/example.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..f154d09dde94d233388013a20e60ffd092c59953 GIT binary patch literal 22643 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 0 { + return errors.New(string(out)) + } + + return err + } + + return nil +} + +func validateJPEG(path string, requireSize int) error { + file, err := os.OpenFile(path, os.O_RDONLY, 0) + if err != nil { + return err + } + + defer file.Close() + + img, err := jpeg.Decode(file) + if err != nil { + return err + } + + bounds := img.Bounds() + + if bounds.Dx() == 0 || bounds.Dy() == 0 { + return fmt.Errorf("invalid dimensions: %dx%d", bounds.Dx(), bounds.Dy()) + } + + if requireSize != 0 && (bounds.Dx() != requireSize || bounds.Dy() != requireSize) { + return fmt.Errorf("mismatched size: %dx%dx", bounds.Dx(), bounds.Dy()) + } + + return nil +} diff --git a/internal/codec/detect.go b/internal/codec/detect.go index 291a968..e28c612 100644 --- a/internal/codec/detect.go +++ b/internal/codec/detect.go @@ -33,7 +33,7 @@ func Sniff(reader io.Reader, input string, ignoreExtension bool) (*Sniffed, io.R if !ignoreExtension { ext := strings.ToLower(strings.TrimPrefix(filepath.Ext(input), ".")) if ext != "" { - codec, _ := FindCodec(ext) + codec, _ := FindCodec(ext, false) if codec != nil { return &Sniffed{ Header: []byte("." + ext), @@ -95,7 +95,7 @@ func Detect(output, override string) (Codec, string, error) { } } - codec, err := FindCodec(ext) + codec, err := FindCodec(ext, true) if err != nil { return nil, "", err } @@ -107,7 +107,7 @@ func Detect(output, override string) (Codec, string, error) { return codec, ext, nil } -func FindCodec(ext string) (Codec, error) { +func FindCodec(ext string, requireEncode bool) (Codec, error) { codec, ok := codecs[ext] if ok { return codec, nil @@ -116,7 +116,7 @@ func FindCodec(ext string) (Codec, error) { for _, codec := range codecs { for _, alias := range codec.Extensions() { if ext == alias { - if !codec.CanEncode() { + if requireEncode && !codec.CanEncode() { return nil, fmt.Errorf("decode-only output codec: %q", ext) }