1
2
3
4
5 package cmpimg
6
7 import (
8 "bytes"
9 "encoding/base64"
10 "flag"
11 "image"
12 "image/png"
13 "os"
14 "path/filepath"
15 "strings"
16 "testing"
17 )
18
19 var GenerateTestData = flag.Bool("regen", false, "Uses the current state to regenerate the test data.")
20
21 func goldenPath(path string) string {
22 ext := filepath.Ext(path)
23 noext := strings.TrimSuffix(path, ext)
24 return noext + "_golden" + ext
25 }
26
27
28
29
30
31 func CheckPlot(ExampleFunc func(), t *testing.T, filenames ...string) {
32 CheckPlotApprox(ExampleFunc, t, 0, filenames...)
33 }
34
35
36
37
38
39
40
41 func CheckPlotApprox(ExampleFunc func(), t *testing.T, delta float64, filenames ...string) {
42 t.Helper()
43
44 paths := make([]string, len(filenames))
45 for i, fn := range filenames {
46 paths[i] = filepath.Join("testdata", fn)
47 }
48
49 if *GenerateTestData {
50
51 ExampleFunc()
52 for _, path := range paths {
53 golden := goldenPath(path)
54 _ = os.Remove(golden)
55 if err := os.Rename(path, golden); err != nil {
56 t.Fatal(err)
57 }
58 }
59 return
60 }
61
62
63 ExampleFunc()
64
65
66
67 for _, path := range paths {
68 got, err := os.ReadFile(path)
69 if err != nil {
70 t.Errorf("Failed to read %s: %v", path, err)
71 continue
72 }
73 golden := goldenPath(path)
74 want, err := os.ReadFile(golden)
75 if err != nil {
76 t.Errorf("Failed to read golden file %s: %v", golden, err)
77 continue
78 }
79 typ := filepath.Ext(path)[1:]
80 ok, err := EqualApprox(typ, got, want, delta)
81 if err != nil {
82 t.Errorf("failed to compare image for %s: %v", path, err)
83 continue
84 }
85 if !ok {
86 t.Errorf("image mismatch for %s\n", path)
87
88 switch typ {
89 case "jpeg", "jpg", "png", "tiff", "tif":
90 v1, _, err := image.Decode(bytes.NewReader(got))
91 if err != nil {
92 t.Errorf("failed to decode %s: %v", path, err)
93 continue
94 }
95 v2, _, err := image.Decode(bytes.NewReader(want))
96 if err != nil {
97 t.Errorf("failed to decode %s: %v", golden, err)
98 continue
99 }
100
101 dst := image.NewRGBA64(v1.Bounds().Union(v2.Bounds()))
102 rect := Diff(dst, v1, v2)
103 t.Logf("image bounds union:%+v diff bounds intersection:%+v", dst.Bounds(), rect)
104
105 var buf bytes.Buffer
106 err = png.Encode(&buf, dst)
107 if err != nil {
108 t.Errorf("failed to encode difference png: %v", err)
109 continue
110 }
111 t.Log("image diff:")
112 t.Log("IMAGE:" + base64.StdEncoding.EncodeToString(buf.Bytes()))
113
114 buf.Reset()
115 err = png.Encode(&buf, v1)
116 if err != nil {
117 t.Errorf("failed to encode result png: %+v", err)
118 continue
119 }
120 t.Log("image check:")
121 t.Log("IMAGE:" + base64.StdEncoding.EncodeToString(buf.Bytes()))
122 }
123 }
124 }
125 }
126
View as plain text