-
Notifications
You must be signed in to change notification settings - Fork 27
/
golden.go
120 lines (94 loc) · 3.23 KB
/
golden.go
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Package testutils provides utility functions and behaviors for testing.
package testutils
import (
"flag"
"os"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
)
var update bool
type goldenOptions struct {
goldenPath string
}
// GoldenOption is a supported option reference to change the golden files comparison.
type GoldenOption func(*goldenOptions)
// WithGoldenPath overrides the default path for golden files used.
func WithGoldenPath(path string) GoldenOption {
return func(o *goldenOptions) {
if path != "" {
o.goldenPath = path
}
}
}
// LoadWithUpdateFromGolden loads the element from a plaintext golden file.
// It will update the file if the update flag is used prior to loading it.
func LoadWithUpdateFromGolden(t *testing.T, data string, opts ...GoldenOption) string {
t.Helper()
o := goldenOptions{
goldenPath: GoldenPath(t),
}
for _, opt := range opts {
opt(&o)
}
if update {
t.Logf("updating golden file %s", o.goldenPath)
err := os.MkdirAll(filepath.Dir(o.goldenPath), 0750)
require.NoError(t, err, "Cannot create directory for updating golden files")
err = os.WriteFile(o.goldenPath, []byte(data), 0600)
require.NoError(t, err, "Cannot write golden file")
}
want, err := os.ReadFile(o.goldenPath)
require.NoError(t, err, "Cannot load golden file")
return string(want)
}
// LoadWithUpdateFromGoldenYAML load the generic element from a YAML serialized golden file.
// It will update the file if the update flag is used prior to deserializing it.
func LoadWithUpdateFromGoldenYAML[E any](t *testing.T, got E, opts ...GoldenOption) E {
t.Helper()
t.Logf("Serializing object for golden file")
data, err := yaml.Marshal(got)
require.NoError(t, err, "Cannot serialize provided object")
want := LoadWithUpdateFromGolden(t, string(data), opts...)
var wantDeserialized E
err = yaml.Unmarshal([]byte(want), &wantDeserialized)
require.NoError(t, err, "Cannot create expanded policy objects from golden file")
return wantDeserialized
}
// NormalizeGoldenName returns the name of the golden file with illegal Windows
// characters replaced or removed.
func NormalizeGoldenName(t *testing.T, name string) string {
t.Helper()
name = strings.ReplaceAll(name, `\`, "_")
name = strings.ReplaceAll(name, ":", "")
name = strings.ToLower(name)
return name
}
// TestFamilyPath returns the path of the dir for storing fixtures and other files related to the test.
func TestFamilyPath(t *testing.T) string {
t.Helper()
// Ensures that only the name of the parent test is used.
super, _, _ := strings.Cut(t.Name(), "/")
return filepath.Join("testdata", super)
}
// GoldenPath returns the golden path for the provided test.
func GoldenPath(t *testing.T) string {
t.Helper()
path := filepath.Join(TestFamilyPath(t), "golden")
_, sub, found := strings.Cut(t.Name(), "/")
if found {
path = filepath.Join(path, NormalizeGoldenName(t, sub))
}
return path
}
// InstallUpdateFlag install an update flag referenced in this package.
// The flags need to be parsed before running the tests.
func InstallUpdateFlag() {
flag.BoolVar(&update, "update", false, "update golden files")
}
// Update returns true if the update flag was set, false otherwise.
func Update() bool {
return update
}