1
0
mirror of https://github.com/coalaura/ffwebp.git synced 2025-09-08 05:49:54 +00:00
This commit is contained in:
Laura
2025-08-13 03:17:07 +02:00
parent 09a41d0e8e
commit 96df5c36fa

View File

@@ -1,4 +1,3 @@
// integration/integration_test.go
package integration package integration
import ( import (
@@ -13,35 +12,35 @@ import (
"gotest.tools/v3/icmd" "gotest.tools/v3/icmd"
) )
// Skip encoding tests for these extensions (same semantics as your original) var (
var encodeOnly = map[string]bool{ executable = "ffwebp"
"heic": true, encodeOnly = map[string]bool{
"heif": true, "heic": true,
"psd": true, "heif": true,
"svg": true, "psd": true,
} "svg": true,
}
const (
fixturesDir = "images" // integration/images/
exampleJPEG = "example.jpeg" // integration/example.jpeg (256x256)
) )
var ffwebpBin string // set in TestMain const (
fixturesDir = "images"
exampleJPEG = "example.jpeg"
)
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
// Build the CLI once with -tags=full into a temp dir, reusing it across tests.
tmp, err := os.MkdirTemp("", "ffwebp-bin-*") tmp, err := os.MkdirTemp("", "ffwebp-bin-*")
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "mktemp:", err) fmt.Fprintln(os.Stderr, err)
os.Exit(1) os.Exit(1)
} }
defer os.RemoveAll(tmp) defer os.RemoveAll(tmp)
exe := "ffwebp"
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
exe += ".exe" executable += ".exe"
} }
ffwebpBin = filepath.Join(tmp, exe)
executable = filepath.Join(tmp, executable)
root, err := findRepoRoot() root, err := findRepoRoot()
if err != nil { if err != nil {
@@ -49,9 +48,10 @@ func TestMain(m *testing.M) {
os.Exit(1) os.Exit(1)
} }
// Build from repo root so relative paths to ./cmd/ffwebp resolve. build := icmd.Command("go", "build", "-tags=full", "-o", executable, "./cmd/ffwebp")
build := icmd.Command("go", "build", "-tags=full", "-o", ffwebpBin, "./cmd/ffwebp")
build.Dir = root build.Dir = root
res := icmd.RunCmd(build) res := icmd.RunCmd(build)
if res.ExitCode != 0 { if res.ExitCode != 0 {
fmt.Fprintln(os.Stderr, res.Combined()) fmt.Fprintln(os.Stderr, res.Combined())
@@ -62,7 +62,6 @@ func TestMain(m *testing.M) {
} }
func TestCLI_CodecDecodeAndRoundTrip(t *testing.T) { func TestCLI_CodecDecodeAndRoundTrip(t *testing.T) {
// Discover input samples: integration/images/image.<ext>
entries, err := os.ReadDir(fixturesDir) entries, err := os.ReadDir(fixturesDir)
if err != nil { if err != nil {
t.Fatalf("read %s: %v", fixturesDir, err) t.Fatalf("read %s: %v", fixturesDir, err)
@@ -72,38 +71,41 @@ func TestCLI_CodecDecodeAndRoundTrip(t *testing.T) {
if e.IsDir() { if e.IsDir() {
continue continue
} }
inPath := filepath.Join(fixturesDir, e.Name()) inPath := filepath.Join(fixturesDir, e.Name())
ext := strings.TrimPrefix(filepath.Ext(e.Name()), ".") ext := strings.TrimPrefix(filepath.Ext(e.Name()), ".")
// 1) <codec> -> jpeg // test going from codec to jpeg
t.Run("decode_"+ext, func(t *testing.T) { t.Run("decode_"+ext, func(t *testing.T) {
tmp := t.TempDir() tmp := t.TempDir()
out := filepath.Join(tmp, "decoded.jpeg") out := filepath.Join(tmp, "decoded.jpeg")
run(t, icmd.Command(ffwebpBin, "-s", "-i", inPath, "-o", out)) run(t, icmd.Command(executable, "-s", "-i", inPath, "-o", out))
w, h := jpegSize(t, out) w, h := jpegSize(t, out)
if w == 0 || h == 0 { if w == 0 || h == 0 {
t.Fatalf("decoded JPEG has invalid size: %dx%d", w, h) t.Fatalf("decoded JPEG has no size: %dx%d", w, h)
} }
}) })
// 2) jpeg -> <codec> -> jpeg (dimension stays 256x256), unless encodeOnly // test going from jpeg to codec then back to jpeg
if encodeOnly[ext] { if encodeOnly[ext] {
continue continue
} }
t.Run("encode_"+ext, func(t *testing.T) { t.Run("encode_"+ext, func(t *testing.T) {
tmp := t.TempDir() tmp := t.TempDir()
mid := filepath.Join(tmp, "encoded."+ext) mid := filepath.Join(tmp, "encoded."+ext)
back := filepath.Join(tmp, "roundtrip.jpeg") back := filepath.Join(tmp, "roundtrip.jpeg")
run(t, icmd.Command(ffwebpBin, "-s", "-i", exampleJPEG, "-o", mid)) run(t, icmd.Command(executable, "-s", "-i", exampleJPEG, "-o", mid))
run(t, icmd.Command(ffwebpBin, "-s", "-i", mid, "-o", back)) run(t, icmd.Command(executable, "-s", "-i", mid, "-o", back))
w, h := jpegSize(t, back) w, h := jpegSize(t, back)
if w != 256 || h != 256 { if w != 256 || h != 256 {
t.Fatalf("roundtrip dimension mismatch: got %dx%d, want 256x256", w, h) t.Fatalf("dimension mismatch: got %dx%d, want 256x256", w, h)
} }
}) })
} }
@@ -111,40 +113,47 @@ func TestCLI_CodecDecodeAndRoundTrip(t *testing.T) {
func run(t *testing.T, cmd icmd.Cmd) { func run(t *testing.T, cmd icmd.Cmd) {
t.Helper() t.Helper()
res := icmd.RunCmd(cmd) res := icmd.RunCmd(cmd)
// On failure, icmd prints the command line + stdout/stderr, which is handy.
res.Assert(t, icmd.Success) res.Assert(t, icmd.Success)
} }
func jpegSize(t *testing.T, path string) (int, int) { func jpegSize(t *testing.T, path string) (int, int) {
t.Helper() t.Helper()
f, err := os.Open(path)
f, err := os.OpenFile(path, os.O_RDONLY, 0)
if err != nil { if err != nil {
t.Fatalf("open %s: %v", path, err) t.Fatalf("open %s: %v", path, err)
} }
defer f.Close() defer f.Close()
cfg, err := jpeg.DecodeConfig(f) cfg, err := jpeg.DecodeConfig(f)
if err != nil { if err != nil {
t.Fatalf("decode jpeg config %s: %v", path, err) t.Fatalf("decode jpeg config %s: %v", path, err)
} }
return cfg.Width, cfg.Height return cfg.Width, cfg.Height
} }
func findRepoRoot() (string, error) { func findRepoRoot() (string, error) {
// Walk up to find go.mod so we can run `go build ./cmd/ffwebp` reliably.
dir, err := os.Getwd() dir, err := os.Getwd()
if err != nil { if err != nil {
return "", err return "", err
} }
for { for {
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
return dir, nil return dir, nil
} }
parent := filepath.Dir(dir) parent := filepath.Dir(dir)
if parent == dir { if parent == dir {
return "", fmt.Errorf("could not locate go.mod starting from %s", dir) return "", fmt.Errorf("could not locate go.mod starting from %s", dir)
} }
dir = parent dir = parent
} }
} }