1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
|
// Copyright ©2015 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cmpimg
import (
"bytes"
"encoding/base64"
"flag"
"image"
"image/png"
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
)
var GenerateTestData = flag.Bool("regen", false, "Uses the current state to regenerate the test data.")
func goldenPath(path string) string {
ext := filepath.Ext(path)
noext := strings.TrimSuffix(path, ext)
return noext + "_golden" + ext
}
// CheckPlot checks a generated plot against a previously created reference.
// If generateTestData = true, it regenerates the reference.
// For image.Image formats, a base64 encoded png representation is output to
// the testing log when a difference is identified.
func CheckPlot(ExampleFunc func(), t *testing.T, filenames ...string) {
paths := make([]string, len(filenames))
for i, fn := range filenames {
paths[i] = filepath.Join("testdata", fn)
}
if *GenerateTestData {
// Recreate Golden images and exit.
ExampleFunc()
for _, path := range paths {
golden := goldenPath(path)
_ = os.Remove(golden)
if err := os.Rename(path, golden); err != nil {
t.Fatal(err)
}
}
return
}
// Run the example.
ExampleFunc()
// Read the images we've just generated and check them against the
// Golden Images.
for _, path := range paths {
got, err := ioutil.ReadFile(path)
if err != nil {
t.Errorf("Failed to read %s: %v", path, err)
continue
}
golden := goldenPath(path)
want, err := ioutil.ReadFile(golden)
if err != nil {
t.Errorf("Failed to read golden file %s: %v", golden, err)
continue
}
typ := filepath.Ext(path)[1:] // remove the dot in e.g. ".pdf"
ok, err := Equal(typ, got, want)
if err != nil {
t.Errorf("failed to compare image for %s: %v", path, err)
continue
}
if !ok {
t.Errorf("image mismatch for %s\n", path)
switch typ {
case "jpeg", "jpg", "png", "tiff", "tif":
v1, _, err := image.Decode(bytes.NewReader(got))
if err != nil {
t.Errorf("failed to decode %s: %v", path, err)
continue
}
v2, _, err := image.Decode(bytes.NewReader(want))
if err != nil {
t.Errorf("failed to decode %s: %v", golden, err)
continue
}
dst := image.NewRGBA64(v1.Bounds().Union(v2.Bounds()))
rect := Diff(dst, v1, v2)
t.Logf("image bounds union:%+v diff bounds intersection:%+v", dst.Bounds(), rect)
var buf bytes.Buffer
err = png.Encode(&buf, dst)
if err != nil {
t.Errorf("failed to encode difference png: %v", err)
continue
}
t.Log("IMAGE:" + base64.StdEncoding.EncodeToString(buf.Bytes()))
}
}
}
}
|