diff --git a/resources/images/images_golden_integration_test.go b/resources/images/images_golden_integration_test.go index 49d90a79394..526e3ba534c 100644 --- a/resources/images/images_golden_integration_test.go +++ b/resources/images/images_golden_integration_test.go @@ -14,63 +14,22 @@ package images_test import ( - "image" - "image/gif" _ "image/jpeg" - "io/fs" - "os" - "path/filepath" - "runtime" - "strings" "testing" - "github.com/disintegration/gift" - qt "github.com/frankban/quicktest" - "github.com/gohugoio/hugo/common/hashing" - "github.com/gohugoio/hugo/common/hugio" - "github.com/gohugoio/hugo/htesting" - "github.com/gohugoio/hugo/hugofs" - "github.com/gohugoio/hugo/hugolib" - "github.com/google/go-cmp/cmp" + "github.com/gohugoio/hugo/resources/images/imagetesting" ) -var eq = qt.CmpEquals( - cmp.Comparer(func(p1, p2 os.FileInfo) bool { - return p1.Name() == p2.Name() && p1.Size() == p2.Size() && p1.IsDir() == p2.IsDir() - }), - cmp.Comparer(func(d1, d2 fs.DirEntry) bool { - p1, err1 := d1.Info() - p2, err2 := d2.Info() - if err1 != nil || err2 != nil { - return false - } - return p1.Name() == p2.Name() && p1.Size() == p2.Size() && p1.IsDir() == p2.IsDir() - }), -) - -var goldenOpts = struct { - // Toggle this to write golden files to disk. - // Note: Remember to set this to false before committing. - writeGoldenFiles bool - - // This will skip any assertions. Useful when adding new golden variants to a test. - devMode bool -}{ - writeGoldenFiles: false, - devMode: false, -} - // Note, if you're enabling writeGoldenFiles on a MacOS ARM 64 you need to run the test with GOARCH=amd64, e.g. -// GOARCH=amd64 go test -count 1 -timeout 30s -run "^TestGolden" ./resources/images -func TestGoldenFiltersMisc(t *testing.T) { +func TestImagesGoldenFiltersMisc(t *testing.T) { t.Parallel() - if skipGolden { + if imagetesting.SkipGoldenTests { t.Skip("Skip golden test on this architecture") } - // Will be used to generate golden files. - name := "filters_misc" + // Will be used as the base folder for generated images. + name := "filters/misc" files := ` -- hugo.toml -- @@ -82,9 +41,9 @@ sourcefilename: ../testdata/sunset.jpg sourcefilename: ../testdata/gopher-hero8.png -- layouts/index.html -- Home. -{{ $sunset := resources.Get "sunset.jpg" }} +{{ $sunset := (resources.Get "sunset.jpg").Resize "x300" }} {{ $sunsetGrayscale := $sunset.Filter (images.Grayscale) }} -{{ $gopher := resources.Get "gopher.png" }} +{{ $gopher := (resources.Get "gopher.png").Resize "x80" }} {{ $overlayFilter := images.Overlay $gopher 20 20 }} {{ $textOpts := dict @@ -130,18 +89,23 @@ Home. {{ end }} ` - runGolden(t, name, files) + opts := imagetesting.DefaultGoldenOpts + opts.T = t + opts.Name = name + opts.Files = files + + imagetesting.RunGolden(opts) } -func TestGoldenFiltersMask(t *testing.T) { +func TestImagesGoldenFiltersMask(t *testing.T) { t.Parallel() - if skipGolden { + if imagetesting.SkipGoldenTests { t.Skip("Skip golden test on this architecture") } - // Will be used to generate golden files. - name := "filters_mask" + // Will be used as the base folder for generated images. + name := "filters/mask" files := ` -- hugo.toml -- @@ -163,7 +127,12 @@ Home. {{ template "mask" (dict "name" "transparant.png" "base" $sunset "mask" $mask) }} {{ template "mask" (dict "name" "yellow.jpg" "base" $sunset "mask" $mask) }} {{ template "mask" (dict "name" "wide.jpg" "base" $sunset "mask" $mask "spec" "resize 600x200") }} - +{{/* This looks a little odd, but is correct and the recommended way to do this. +This will 1. Scale the image to x300, 2. Apply the mask, 3. Create the final image with background color #323ea. +It's possible to have multiple images.Process filters in the chain, but for the options for the final image (target format, bgGolor etc.), +the last entry will win. +*/}} +{{ template "mask" (dict "name" "blue.jpg" "base" $sunset "mask" $mask "spec" "resize x300 #323ea8") }} {{ define "mask"}} {{ $ext := path.Ext .name }} @@ -171,7 +140,7 @@ Home. {{ errorf "No extension in %q" .name }} {{ end }} {{ $format := strings.TrimPrefix "." $ext }} -{{ $spec := .spec | default (printf "resize 300x300 %s" $format) }} +{{ $spec := .spec | default (printf "resize x300 %s" $format) }} {{ $filters := slice (images.Process $spec) (images.Mask .mask) }} {{ $name := printf "images/%s" .name }} {{ $img := .base.Filter $filters }} @@ -181,18 +150,23 @@ Home. {{ end }} ` - runGolden(t, name, files) + opts := imagetesting.DefaultGoldenOpts + opts.T = t + opts.Name = name + opts.Files = files + + imagetesting.RunGolden(opts) } -func TestGoldenFiltersText(t *testing.T) { +func TestImagesGoldenFiltersText(t *testing.T) { t.Parallel() - if skipGolden { + if imagetesting.SkipGoldenTests { t.Skip("Skip golden test on this architecture") } - // Will be used to generate golden files. - name := "filters_text" + // Will be used as the base folder for generated images. + name := "filters/text" files := ` -- hugo.toml -- @@ -230,18 +204,23 @@ Home. {{ end }} ` - runGolden(t, name, files) + opts := imagetesting.DefaultGoldenOpts + opts.T = t + opts.Name = name + opts.Files = files + + imagetesting.RunGolden(opts) } -func TestGoldenProcessMisc(t *testing.T) { +func TestImagesGoldenProcessMisc(t *testing.T) { t.Parallel() - if skipGolden { + if imagetesting.SkipGoldenTests { t.Skip("Skip golden test on this architecture") } - // Will be used to generate golden files. - name := "process_misc" + // Will be used as the base folder for generated images. + name := "process/misc" files := ` -- hugo.toml -- @@ -277,180 +256,10 @@ Home. {{ end }} ` - runGolden(t, name, files) -} - -func TestGoldenFuncs(t *testing.T) { - t.Parallel() - - if skipGolden { - t.Skip("Skip golden test on this architecture") - } - - // Will be used to generate golden files. - name := "funcs" - - files := ` --- hugo.toml -- --- assets/sunset.jpg -- -sourcefilename: ../testdata/sunset.jpg - --- layouts/index.html -- -Home. - -{{ template "copy" (dict "name" "qr-default.png" "img" (images.QR "https://gohugo.io")) }} -{{ template "copy" (dict "name" "qr-level-high_scale-6.png" "img" (images.QR "https://gohugo.io" (dict "level" "high" "scale" 6))) }} - -{{ define "copy"}} -{{ if lt (len (path.Ext .name)) 4 }} - {{ errorf "No extension in %q" .name }} -{{ end }} -{{ $img := .img }} -{{ $name := printf "images/%s" .name }} -{{ with $img | resources.Copy $name }} -{{ .Publish }} -{{ end }} -{{ end }} -` - - runGolden(t, name, files) -} - -func runGolden(t testing.TB, name, files string) *hugolib.IntegrationTestBuilder { - t.Helper() - - c := hugolib.Test(t, files, hugolib.TestOptWithOSFs()) // hugolib.TestOptWithPrintAndKeepTempDir(true)) - c.AssertFileContent("public/index.html", "Home.") - - outputDir := filepath.Join(c.H.Conf.WorkingDir(), "public", "images") - goldenBaseDir := filepath.Join("testdata", "images_golden") - goldenDir := filepath.Join(goldenBaseDir, name) - if goldenOpts.writeGoldenFiles { - c.Assert(htesting.IsRealCI(), qt.IsFalse) - c.Assert(os.MkdirAll(goldenBaseDir, 0o777), qt.IsNil) - c.Assert(os.RemoveAll(goldenDir), qt.IsNil) - c.Assert(hugio.CopyDir(hugofs.Os, outputDir, goldenDir, nil), qt.IsNil) - return c - } + opts := imagetesting.DefaultGoldenOpts + opts.T = t + opts.Name = name + opts.Files = files - if goldenOpts.devMode { - c.Assert(htesting.IsRealCI(), qt.IsFalse) - return c - } - - decodeAll := func(f *os.File) []image.Image { - c.Helper() - - var images []image.Image - - if strings.HasSuffix(f.Name(), ".gif") { - gif, err := gif.DecodeAll(f) - c.Assert(err, qt.IsNil, qt.Commentf(f.Name())) - images = make([]image.Image, len(gif.Image)) - for i, img := range gif.Image { - images[i] = img - } - } else { - img, _, err := image.Decode(f) - c.Assert(err, qt.IsNil, qt.Commentf(f.Name())) - images = append(images, img) - } - return images - } - - entries1, err := os.ReadDir(outputDir) - c.Assert(err, qt.IsNil) - entries2, err := os.ReadDir(goldenDir) - c.Assert(err, qt.IsNil) - c.Assert(len(entries1), qt.Equals, len(entries2)) - for i, e1 := range entries1 { - c.Assert(filepath.Ext(e1.Name()), qt.Not(qt.Equals), "") - func() { - e2 := entries2[i] - - f1, err := os.Open(filepath.Join(outputDir, e1.Name())) - c.Assert(err, qt.IsNil) - defer f1.Close() - - f2, err := os.Open(filepath.Join(goldenDir, e2.Name())) - c.Assert(err, qt.IsNil) - defer f2.Close() - - imgs2 := decodeAll(f2) - imgs1 := decodeAll(f1) - c.Assert(len(imgs1), qt.Equals, len(imgs2)) - - if !usesFMA { - c.Assert(e1, eq, e2) - _, err = f1.Seek(0, 0) - c.Assert(err, qt.IsNil) - _, err = f2.Seek(0, 0) - c.Assert(err, qt.IsNil) - - hash1, _, err := hashing.XXHashFromReader(f1) - c.Assert(err, qt.IsNil) - hash2, _, err := hashing.XXHashFromReader(f2) - c.Assert(err, qt.IsNil) - - c.Assert(hash1, qt.Equals, hash2) - } - - for i, img1 := range imgs1 { - img2 := imgs2[i] - nrgba1 := image.NewNRGBA(img1.Bounds()) - gift.New().Draw(nrgba1, img1) - nrgba2 := image.NewNRGBA(img2.Bounds()) - gift.New().Draw(nrgba2, img2) - c.Assert(goldenEqual(nrgba1, nrgba2), qt.Equals, true, qt.Commentf(e1.Name())) - } - }() - } - return c + imagetesting.RunGolden(opts) } - -// goldenEqual compares two NRGBA images. It is used in golden tests only. -// A small tolerance is allowed on architectures using "fused multiply and add" -// (FMA) instruction to accommodate for floating-point rounding differences -// with control golden images that were generated on amd64 architecture. -// See https://golang.org/ref/spec#Floating_point_operators -// and https://github.com/gohugoio/hugo/issues/6387 for more information. -// -// Based on https://github.com/disintegration/gift/blob/a999ff8d5226e5ab14b64a94fca07c4ac3f357cf/gift_test.go#L598-L625 -// Copyright (c) 2014-2019 Grigory Dryapak -// Licensed under the MIT License. -func goldenEqual(img1, img2 *image.NRGBA) bool { - maxDiff := 0 - if runtime.GOARCH != "amd64" { - // The golden files are created using the AMD64 architecture. - // Be lenient on other platforms due to floaging point and dithering differences. - maxDiff = 15 - } - if !img1.Rect.Eq(img2.Rect) { - return false - } - if len(img1.Pix) != len(img2.Pix) { - return false - } - for i := 0; i < len(img1.Pix); i++ { - diff := int(img1.Pix[i]) - int(img2.Pix[i]) - if diff < 0 { - diff = -diff - } - if diff > maxDiff { - return false - } - } - return true -} - -// We don't have a CI test environment for these, and there are known dithering issues that makes these time consuming to maintain. -var skipGolden = runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x" - -// usesFMA indicates whether "fused multiply and add" (FMA) instruction is -// used. The command "grep FMADD go/test/codegen/floats.go" can help keep -// the FMA-using architecture list updated. -var usesFMA = runtime.GOARCH == "s390x" || - runtime.GOARCH == "ppc64" || - runtime.GOARCH == "ppc64le" || - runtime.GOARCH == "arm64" || - runtime.GOARCH == "riscv64" diff --git a/resources/images/imagetesting/testing.go b/resources/images/imagetesting/testing.go new file mode 100644 index 00000000000..8e00751e0c2 --- /dev/null +++ b/resources/images/imagetesting/testing.go @@ -0,0 +1,215 @@ +// Copyright 2024 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package imagetesting + +import ( + "image" + "image/gif" + "io/fs" + "os" + "path/filepath" + "runtime" + "strings" + "testing" + + qt "github.com/frankban/quicktest" + "github.com/google/go-cmp/cmp" + + "github.com/disintegration/gift" + "github.com/gohugoio/hugo/common/hashing" + "github.com/gohugoio/hugo/common/hugio" + "github.com/gohugoio/hugo/htesting" + "github.com/gohugoio/hugo/hugofs" + "github.com/gohugoio/hugo/hugolib" +) + +var eq = qt.CmpEquals( + cmp.Comparer(func(p1, p2 os.FileInfo) bool { + return p1.Name() == p2.Name() && p1.Size() == p2.Size() && p1.IsDir() == p2.IsDir() + }), + cmp.Comparer(func(d1, d2 fs.DirEntry) bool { + p1, err1 := d1.Info() + p2, err2 := d2.Info() + if err1 != nil || err2 != nil { + return false + } + return p1.Name() == p2.Name() && p1.Size() == p2.Size() && p1.IsDir() == p2.IsDir() + }), +) + +// GoldenImageTestOpts provides options for a golden image test. +type GoldenImageTestOpts struct { + // The test. + T testing.TB + + // Name of the test. Will be used as the base folder for generated images. + // Slashes allowed and encouraged. + Name string + + // The test site's files in txttar format. + Files string + + // Set to true to write golden files to disk. + WriteFiles bool + + // Set to true to skip any assertions. Useful when adding new golden variants to a test. + DevMode bool +} + +// To rebuild all Golden image tests, toggle WriteFiles=true and run: +// GOARCH=amd64 go test -count 1 -timeout 30s -run "^TestImagesGolden" ./... +// TODO(bep) see if we can do this via flags. +var DefaultGoldenOpts = GoldenImageTestOpts{ + WriteFiles: false, + DevMode: false, +} + +func RunGolden(opts GoldenImageTestOpts) *hugolib.IntegrationTestBuilder { + opts.T.Helper() + + c := hugolib.Test(opts.T, opts.Files, hugolib.TestOptWithOSFs()) // hugolib.TestOptWithPrintAndKeepTempDir(true)) + c.AssertFileContent("public/index.html", "Home.") + + outputDir := filepath.Join(c.H.Conf.WorkingDir(), "public", "images") + goldenBaseDir := filepath.Join("testdata", "images_golden") + goldenDir := filepath.Join(goldenBaseDir, filepath.FromSlash(opts.Name)) + if opts.WriteFiles { + c.Assert(htesting.IsRealCI(), qt.IsFalse) + c.Assert(os.MkdirAll(goldenBaseDir, 0o777), qt.IsNil) + c.Assert(os.RemoveAll(goldenDir), qt.IsNil) + c.Assert(hugio.CopyDir(hugofs.Os, outputDir, goldenDir, nil), qt.IsNil) + return c + } + + if opts.DevMode { + c.Assert(htesting.IsRealCI(), qt.IsFalse) + return c + } + + decodeAll := func(f *os.File) []image.Image { + c.Helper() + + var images []image.Image + + if strings.HasSuffix(f.Name(), ".gif") { + gif, err := gif.DecodeAll(f) + c.Assert(err, qt.IsNil, qt.Commentf(f.Name())) + images = make([]image.Image, len(gif.Image)) + for i, img := range gif.Image { + images[i] = img + } + } else { + img, _, err := image.Decode(f) + c.Assert(err, qt.IsNil, qt.Commentf(f.Name())) + images = append(images, img) + } + return images + } + + entries1, err := os.ReadDir(outputDir) + c.Assert(err, qt.IsNil) + entries2, err := os.ReadDir(goldenDir) + c.Assert(err, qt.IsNil) + c.Assert(len(entries1), qt.Equals, len(entries2)) + for i, e1 := range entries1 { + c.Assert(filepath.Ext(e1.Name()), qt.Not(qt.Equals), "") + func() { + e2 := entries2[i] + + f1, err := os.Open(filepath.Join(outputDir, e1.Name())) + c.Assert(err, qt.IsNil) + defer f1.Close() + + f2, err := os.Open(filepath.Join(goldenDir, e2.Name())) + c.Assert(err, qt.IsNil) + defer f2.Close() + + imgs2 := decodeAll(f2) + imgs1 := decodeAll(f1) + c.Assert(len(imgs1), qt.Equals, len(imgs2)) + + if !UsesFMA { + c.Assert(e1, eq, e2) + _, err = f1.Seek(0, 0) + c.Assert(err, qt.IsNil) + _, err = f2.Seek(0, 0) + c.Assert(err, qt.IsNil) + + hash1, _, err := hashing.XXHashFromReader(f1) + c.Assert(err, qt.IsNil) + hash2, _, err := hashing.XXHashFromReader(f2) + c.Assert(err, qt.IsNil) + + c.Assert(hash1, qt.Equals, hash2) + } + + for i, img1 := range imgs1 { + img2 := imgs2[i] + nrgba1 := image.NewNRGBA(img1.Bounds()) + gift.New().Draw(nrgba1, img1) + nrgba2 := image.NewNRGBA(img2.Bounds()) + gift.New().Draw(nrgba2, img2) + c.Assert(goldenEqual(nrgba1, nrgba2), qt.Equals, true, qt.Commentf(e1.Name())) + } + }() + } + return c +} + +// goldenEqual compares two NRGBA images. It is used in golden tests only. +// A small tolerance is allowed on architectures using "fused multiply and add" +// (FMA) instruction to accommodate for floating-point rounding differences +// with control golden images that were generated on amd64 architecture. +// See https://golang.org/ref/spec#Floating_point_operators +// and https://github.com/gohugoio/hugo/issues/6387 for more information. +// +// Based on https://github.com/disintegration/gift/blob/a999ff8d5226e5ab14b64a94fca07c4ac3f357cf/gift_test.go#L598-L625 +// Copyright (c) 2014-2019 Grigory Dryapak +// Licensed under the MIT License. +func goldenEqual(img1, img2 *image.NRGBA) bool { + maxDiff := 0 + if runtime.GOARCH != "amd64" { + // The golden files are created using the AMD64 architecture. + // Be lenient on other platforms due to floaging point and dithering differences. + maxDiff = 15 + } + if !img1.Rect.Eq(img2.Rect) { + return false + } + if len(img1.Pix) != len(img2.Pix) { + return false + } + for i := 0; i < len(img1.Pix); i++ { + diff := int(img1.Pix[i]) - int(img2.Pix[i]) + if diff < 0 { + diff = -diff + } + if diff > maxDiff { + return false + } + } + return true +} + +// We don't have a CI test environment for these, and there are known dithering issues that makes these time consuming to maintain. +var SkipGoldenTests = runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x" + +// UsesFMA indicates whether "fused multiply and add" (FMA) instruction is +// used. The command "grep FMADD go/test/codegen/floats.go" can help keep +// the FMA-using architecture list updated. +var UsesFMA = runtime.GOARCH == "s390x" || + runtime.GOARCH == "ppc64" || + runtime.GOARCH == "ppc64le" || + runtime.GOARCH == "arm64" || + runtime.GOARCH == "riscv64" diff --git a/resources/images/testdata/images_golden/filters/mask/blue.jpg b/resources/images/testdata/images_golden/filters/mask/blue.jpg new file mode 100644 index 00000000000..7c809774100 Binary files /dev/null and b/resources/images/testdata/images_golden/filters/mask/blue.jpg differ diff --git a/resources/images/testdata/images_golden/filters/mask/transparant.png b/resources/images/testdata/images_golden/filters/mask/transparant.png new file mode 100644 index 00000000000..4d8c57ace5c Binary files /dev/null and b/resources/images/testdata/images_golden/filters/mask/transparant.png differ diff --git a/resources/images/testdata/images_golden/filters_mask/wide.jpg b/resources/images/testdata/images_golden/filters/mask/wide.jpg similarity index 100% rename from resources/images/testdata/images_golden/filters_mask/wide.jpg rename to resources/images/testdata/images_golden/filters/mask/wide.jpg diff --git a/resources/images/testdata/images_golden/filters/mask/yellow.jpg b/resources/images/testdata/images_golden/filters/mask/yellow.jpg new file mode 100644 index 00000000000..e7b3073db21 Binary files /dev/null and b/resources/images/testdata/images_golden/filters/mask/yellow.jpg differ diff --git a/resources/images/testdata/images_golden/filters/misc/brightness-40.jpg b/resources/images/testdata/images_golden/filters/misc/brightness-40.jpg new file mode 100644 index 00000000000..92d03e2f1d0 Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/brightness-40.jpg differ diff --git a/resources/images/testdata/images_golden/filters/misc/colorbalance-180-50-20.jpg b/resources/images/testdata/images_golden/filters/misc/colorbalance-180-50-20.jpg new file mode 100644 index 00000000000..1f34922eb23 Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/colorbalance-180-50-20.jpg differ diff --git a/resources/images/testdata/images_golden/filters/misc/contrast-50.jpg b/resources/images/testdata/images_golden/filters/misc/contrast-50.jpg new file mode 100644 index 00000000000..24a064338b1 Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/contrast-50.jpg differ diff --git a/resources/images/testdata/images_golden/filters/misc/dither-default.jpg b/resources/images/testdata/images_golden/filters/misc/dither-default.jpg new file mode 100644 index 00000000000..3960f94b2f7 Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/dither-default.jpg differ diff --git a/resources/images/testdata/images_golden/filters/misc/gamma-1.667.jpg b/resources/images/testdata/images_golden/filters/misc/gamma-1.667.jpg new file mode 100644 index 00000000000..e8fcbe75383 Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/gamma-1.667.jpg differ diff --git a/resources/images/testdata/images_golden/filters/misc/gaussianblur-5.jpg b/resources/images/testdata/images_golden/filters/misc/gaussianblur-5.jpg new file mode 100644 index 00000000000..36783bb6fd9 Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/gaussianblur-5.jpg differ diff --git a/resources/images/testdata/images_golden/filters/misc/grayscale+colorize-180-50-20.jpg b/resources/images/testdata/images_golden/filters/misc/grayscale+colorize-180-50-20.jpg new file mode 100644 index 00000000000..4902922b373 Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/grayscale+colorize-180-50-20.jpg differ diff --git a/resources/images/testdata/images_golden/filters/misc/grayscale.jpg b/resources/images/testdata/images_golden/filters/misc/grayscale.jpg new file mode 100644 index 00000000000..06617ee00be Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/grayscale.jpg differ diff --git a/resources/images/testdata/images_golden/filters/misc/hue--15.jpg b/resources/images/testdata/images_golden/filters/misc/hue--15.jpg new file mode 100644 index 00000000000..68b191ec2de Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/hue--15.jpg differ diff --git a/resources/images/testdata/images_golden/filters/misc/invert.jpg b/resources/images/testdata/images_golden/filters/misc/invert.jpg new file mode 100644 index 00000000000..69ab0fc1bfb Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/invert.jpg differ diff --git a/resources/images/testdata/images_golden/filters/misc/opacity-0.65.jpg b/resources/images/testdata/images_golden/filters/misc/opacity-0.65.jpg new file mode 100644 index 00000000000..6da3c980e16 Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/opacity-0.65.jpg differ diff --git a/resources/images/testdata/images_golden/filters/misc/overlay-20-20.jpg b/resources/images/testdata/images_golden/filters/misc/overlay-20-20.jpg new file mode 100644 index 00000000000..3a6ca0b3035 Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/overlay-20-20.jpg differ diff --git a/resources/images/testdata/images_golden/filters/misc/padding-20-40-#976941.jpg b/resources/images/testdata/images_golden/filters/misc/padding-20-40-#976941.jpg new file mode 100644 index 00000000000..14a443f9aff Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/padding-20-40-#976941.jpg differ diff --git a/resources/images/testdata/images_golden/filters/misc/pixelate-10.jpg b/resources/images/testdata/images_golden/filters/misc/pixelate-10.jpg new file mode 100644 index 00000000000..094de575e1b Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/pixelate-10.jpg differ diff --git a/resources/images/testdata/images_golden/filters_misc/rotate270.jpg b/resources/images/testdata/images_golden/filters/misc/rotate270.jpg similarity index 100% rename from resources/images/testdata/images_golden/filters_misc/rotate270.jpg rename to resources/images/testdata/images_golden/filters/misc/rotate270.jpg diff --git a/resources/images/testdata/images_golden/filters/misc/saturation-65.jpg b/resources/images/testdata/images_golden/filters/misc/saturation-65.jpg new file mode 100644 index 00000000000..d26585e6644 Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/saturation-65.jpg differ diff --git a/resources/images/testdata/images_golden/filters/misc/sepia-80.jpg b/resources/images/testdata/images_golden/filters/misc/sepia-80.jpg new file mode 100644 index 00000000000..76d08ad8cf8 Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/sepia-80.jpg differ diff --git a/resources/images/testdata/images_golden/filters/misc/sigmoid-0.6--4.jpg b/resources/images/testdata/images_golden/filters/misc/sigmoid-0.6--4.jpg new file mode 100644 index 00000000000..c6df067151c Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/sigmoid-0.6--4.jpg differ diff --git a/resources/images/testdata/images_golden/filters/misc/text.jpg b/resources/images/testdata/images_golden/filters/misc/text.jpg new file mode 100644 index 00000000000..20e79dbad2d Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/text.jpg differ diff --git a/resources/images/testdata/images_golden/filters/misc/unsharpmask.jpg b/resources/images/testdata/images_golden/filters/misc/unsharpmask.jpg new file mode 100644 index 00000000000..9b04b670138 Binary files /dev/null and b/resources/images/testdata/images_golden/filters/misc/unsharpmask.jpg differ diff --git a/resources/images/testdata/images_golden/filters_text/text_alignx-center.jpg b/resources/images/testdata/images_golden/filters/text/text_alignx-center.jpg similarity index 100% rename from resources/images/testdata/images_golden/filters_text/text_alignx-center.jpg rename to resources/images/testdata/images_golden/filters/text/text_alignx-center.jpg diff --git a/resources/images/testdata/images_golden/filters_text/text_alignx-left.jpg b/resources/images/testdata/images_golden/filters/text/text_alignx-left.jpg similarity index 100% rename from resources/images/testdata/images_golden/filters_text/text_alignx-left.jpg rename to resources/images/testdata/images_golden/filters/text/text_alignx-left.jpg diff --git a/resources/images/testdata/images_golden/filters_text/text_alignx-right.jpg b/resources/images/testdata/images_golden/filters/text/text_alignx-right.jpg similarity index 100% rename from resources/images/testdata/images_golden/filters_text/text_alignx-right.jpg rename to resources/images/testdata/images_golden/filters/text/text_alignx-right.jpg diff --git a/resources/images/testdata/images_golden/filters_mask/transparant.png b/resources/images/testdata/images_golden/filters_mask/transparant.png deleted file mode 100644 index ffbd84c9636..00000000000 Binary files a/resources/images/testdata/images_golden/filters_mask/transparant.png and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_mask/yellow.jpg b/resources/images/testdata/images_golden/filters_mask/yellow.jpg deleted file mode 100644 index a87123536ea..00000000000 Binary files a/resources/images/testdata/images_golden/filters_mask/yellow.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/brightness-40.jpg b/resources/images/testdata/images_golden/filters_misc/brightness-40.jpg deleted file mode 100644 index a9aa6540bbe..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/brightness-40.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/colorbalance-180-50-20.jpg b/resources/images/testdata/images_golden/filters_misc/colorbalance-180-50-20.jpg deleted file mode 100644 index 875ec7acac4..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/colorbalance-180-50-20.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/contrast-50.jpg b/resources/images/testdata/images_golden/filters_misc/contrast-50.jpg deleted file mode 100644 index 3aeef7b8672..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/contrast-50.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/dither-default.jpg b/resources/images/testdata/images_golden/filters_misc/dither-default.jpg deleted file mode 100644 index f5a26a7b62f..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/dither-default.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/gamma-1.667.jpg b/resources/images/testdata/images_golden/filters_misc/gamma-1.667.jpg deleted file mode 100644 index 6998b8889f8..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/gamma-1.667.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/gaussianblur-5.jpg b/resources/images/testdata/images_golden/filters_misc/gaussianblur-5.jpg deleted file mode 100644 index c363f744433..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/gaussianblur-5.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/grayscale+colorize-180-50-20.jpg b/resources/images/testdata/images_golden/filters_misc/grayscale+colorize-180-50-20.jpg deleted file mode 100644 index 32b4616cf0c..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/grayscale+colorize-180-50-20.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/grayscale.jpg b/resources/images/testdata/images_golden/filters_misc/grayscale.jpg deleted file mode 100644 index 6db57fee516..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/grayscale.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/hue--15.jpg b/resources/images/testdata/images_golden/filters_misc/hue--15.jpg deleted file mode 100644 index 150cd007eb3..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/hue--15.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/invert.jpg b/resources/images/testdata/images_golden/filters_misc/invert.jpg deleted file mode 100644 index a2cf0cf8205..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/invert.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/opacity-0.65.jpg b/resources/images/testdata/images_golden/filters_misc/opacity-0.65.jpg deleted file mode 100644 index 1198857f6ac..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/opacity-0.65.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/overlay-20-20.jpg b/resources/images/testdata/images_golden/filters_misc/overlay-20-20.jpg deleted file mode 100644 index 1c8963f4286..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/overlay-20-20.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/padding-20-40-#976941.jpg b/resources/images/testdata/images_golden/filters_misc/padding-20-40-#976941.jpg deleted file mode 100644 index f0ac22de7e8..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/padding-20-40-#976941.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/pixelate-10.jpg b/resources/images/testdata/images_golden/filters_misc/pixelate-10.jpg deleted file mode 100644 index a181a73ec29..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/pixelate-10.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/saturation-65.jpg b/resources/images/testdata/images_golden/filters_misc/saturation-65.jpg deleted file mode 100644 index db33a7b25a7..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/saturation-65.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/sepia-80.jpg b/resources/images/testdata/images_golden/filters_misc/sepia-80.jpg deleted file mode 100644 index 8b79d34f99f..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/sepia-80.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/sigmoid-0.6--4.jpg b/resources/images/testdata/images_golden/filters_misc/sigmoid-0.6--4.jpg deleted file mode 100644 index 9dff50a22e4..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/sigmoid-0.6--4.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/text.jpg b/resources/images/testdata/images_golden/filters_misc/text.jpg deleted file mode 100644 index 1c3082bbe58..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/text.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/filters_misc/unsharpmask.jpg b/resources/images/testdata/images_golden/filters_misc/unsharpmask.jpg deleted file mode 100644 index 75164c3f6d9..00000000000 Binary files a/resources/images/testdata/images_golden/filters_misc/unsharpmask.jpg and /dev/null differ diff --git a/resources/images/testdata/images_golden/process_misc/crop-500x200-smart.jpg b/resources/images/testdata/images_golden/process/misc/crop-500x200-smart.jpg similarity index 100% rename from resources/images/testdata/images_golden/process_misc/crop-500x200-smart.jpg rename to resources/images/testdata/images_golden/process/misc/crop-500x200-smart.jpg diff --git a/resources/images/testdata/images_golden/process_misc/fill-500x200-smart.jpg b/resources/images/testdata/images_golden/process/misc/fill-500x200-smart.jpg similarity index 100% rename from resources/images/testdata/images_golden/process_misc/fill-500x200-smart.jpg rename to resources/images/testdata/images_golden/process/misc/fill-500x200-smart.jpg diff --git a/resources/images/testdata/images_golden/process_misc/fit-500x200-smart.jpg b/resources/images/testdata/images_golden/process/misc/fit-500x200-smart.jpg similarity index 100% rename from resources/images/testdata/images_golden/process_misc/fit-500x200-smart.jpg rename to resources/images/testdata/images_golden/process/misc/fit-500x200-smart.jpg diff --git a/resources/images/testdata/images_golden/process_misc/resize-100x100-gif.gif b/resources/images/testdata/images_golden/process/misc/resize-100x100-gif.gif similarity index 100% rename from resources/images/testdata/images_golden/process_misc/resize-100x100-gif.gif rename to resources/images/testdata/images_golden/process/misc/resize-100x100-gif.gif diff --git a/resources/images/testdata/images_golden/process_misc/resize-100x100-r180.png b/resources/images/testdata/images_golden/process/misc/resize-100x100-r180.png similarity index 100% rename from resources/images/testdata/images_golden/process_misc/resize-100x100-r180.png rename to resources/images/testdata/images_golden/process/misc/resize-100x100-r180.png diff --git a/resources/images/testdata/images_golden/process_misc/resize-300x300-jpg-b31280.jpg b/resources/images/testdata/images_golden/process/misc/resize-300x300-jpg-b31280.jpg similarity index 100% rename from resources/images/testdata/images_golden/process_misc/resize-300x300-jpg-b31280.jpg rename to resources/images/testdata/images_golden/process/misc/resize-300x300-jpg-b31280.jpg diff --git a/tpl/images/images_integration_test.go b/tpl/images/images_integration_test.go index 2847128e1f4..22616507026 100644 --- a/tpl/images/images_integration_test.go +++ b/tpl/images/images_integration_test.go @@ -19,6 +19,7 @@ import ( qt "github.com/frankban/quicktest" "github.com/gohugoio/hugo/hugolib" + "github.com/gohugoio/hugo/resources/images/imagetesting" ) func TestImageConfigFromModule(t *testing.T) { @@ -100,3 +101,44 @@ disableKinds = ['page','rss','section','sitemap','taxonomy','term'] b, err = hugolib.TestE(t, files) b.Assert(err.Error(), qt.Contains, "cannot encode an empty string") } + +func TestImagesGoldenFuncs(t *testing.T) { + t.Parallel() + + if imagetesting.SkipGoldenTests { + t.Skip("Skip golden test on this architecture") + } + + // Will be used as the base folder for generated images. + name := "funcs" + + files := ` +-- hugo.toml -- +-- assets/sunset.jpg -- +sourcefilename: ../../resources/testdata/sunset.jpg + +-- layouts/index.html -- +Home. + +{{ template "copy" (dict "name" "qr-default.png" "img" (images.QR "https://gohugo.io")) }} +{{ template "copy" (dict "name" "qr-level-high_scale-6.png" "img" (images.QR "https://gohugo.io" (dict "level" "high" "scale" 6))) }} + +{{ define "copy"}} +{{ if lt (len (path.Ext .name)) 4 }} + {{ errorf "No extension in %q" .name }} +{{ end }} +{{ $img := .img }} +{{ $name := printf "images/%s" .name }} +{{ with $img | resources.Copy $name }} +{{ .Publish }} +{{ end }} +{{ end }} +` + + opts := imagetesting.DefaultGoldenOpts + opts.T = t + opts.Name = name + opts.Files = files + + imagetesting.RunGolden(opts) +} diff --git a/resources/images/testdata/images_golden/funcs/qr-default.png b/tpl/images/testdata/images_golden/funcs/qr-default.png similarity index 100% rename from resources/images/testdata/images_golden/funcs/qr-default.png rename to tpl/images/testdata/images_golden/funcs/qr-default.png diff --git a/resources/images/testdata/images_golden/funcs/qr-level-high_scale-6.png b/tpl/images/testdata/images_golden/funcs/qr-level-high_scale-6.png similarity index 100% rename from resources/images/testdata/images_golden/funcs/qr-level-high_scale-6.png rename to tpl/images/testdata/images_golden/funcs/qr-level-high_scale-6.png