github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/graph/layout/layout_test.go (about) 1 // Copyright ©2019 The Gonum Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package layout_test 6 7 import ( 8 "bytes" 9 "encoding/base64" 10 "image" 11 "image/png" 12 "io/ioutil" 13 "os" 14 "path/filepath" 15 "sort" 16 "strings" 17 "testing" 18 19 "github.com/jingcheng-WU/gonum/graph" 20 "github.com/jingcheng-WU/gonum/graph/internal/ordered" 21 "github.com/jingcheng-WU/gonum/graph/iterator" 22 "gonum.org/v1/plot/cmpimg" 23 ) 24 25 // orderedGraph wraps a graph.Graph ensuring consistent ordering of nodes 26 // in graph queries. Removal of this causes to tests to fail due to changes 27 // in node iteration order, but the produced graph layouts are still good. 28 type orderedGraph struct { 29 graph.Graph 30 } 31 32 func (g orderedGraph) Nodes() graph.Nodes { 33 n := graph.NodesOf(g.Graph.Nodes()) 34 sort.Sort(ordered.ByID(n)) 35 return iterator.NewOrderedNodes(n) 36 } 37 38 func (g orderedGraph) From(id int64) graph.Nodes { 39 n := graph.NodesOf(g.Graph.From(id)) 40 sort.Sort(ordered.ByID(n)) 41 return iterator.NewOrderedNodes(n) 42 } 43 44 func goldenPath(path string) string { 45 ext := filepath.Ext(path) 46 noext := strings.TrimSuffix(path, ext) 47 return noext + "_golden" + ext 48 } 49 50 func checkRenderedLayout(t *testing.T, path string) (ok bool) { 51 if *cmpimg.GenerateTestData { 52 // Recreate Golden image and exit. 53 golden := goldenPath(path) 54 _ = os.Remove(golden) 55 if err := os.Rename(path, golden); err != nil { 56 t.Fatal(err) 57 } 58 return true 59 } 60 61 // Read the images we've just generated and check them against the 62 // Golden Images. 63 got, err := ioutil.ReadFile(path) 64 if err != nil { 65 t.Errorf("failed to read %s: %v", path, err) 66 return true 67 } 68 golden := goldenPath(path) 69 want, err := ioutil.ReadFile(golden) 70 if err != nil { 71 t.Errorf("failed to read golden file %s: %v", golden, err) 72 return true 73 } 74 typ := filepath.Ext(path)[1:] // remove the dot in ".png" 75 ok, err = cmpimg.Equal(typ, got, want) 76 if err != nil { 77 t.Errorf("failed to compare image for %s: %v", path, err) 78 return true 79 } 80 if !ok { 81 t.Errorf("image mismatch for %s\n", path) 82 v1, _, err := image.Decode(bytes.NewReader(got)) 83 if err != nil { 84 t.Errorf("failed to decode %s: %v", path, err) 85 return false 86 } 87 v2, _, err := image.Decode(bytes.NewReader(want)) 88 if err != nil { 89 t.Errorf("failed to decode %s: %v", golden, err) 90 return false 91 } 92 93 dst := image.NewRGBA64(v1.Bounds().Union(v2.Bounds())) 94 rect := cmpimg.Diff(dst, v1, v2) 95 t.Logf("image bounds union:%+v diff bounds intersection:%+v", dst.Bounds(), rect) 96 97 var buf bytes.Buffer 98 err = png.Encode(&buf, dst) 99 if err != nil { 100 t.Errorf("failed to encode difference png: %v", err) 101 return false 102 } 103 t.Log("IMAGE:" + base64.StdEncoding.EncodeToString(buf.Bytes())) 104 } 105 return ok 106 }