1
9 package golden
10
11 import (
12 "bytes"
13 "flag"
14 "fmt"
15 "os"
16 "path/filepath"
17
18 "gotest.tools/v3/assert"
19 "gotest.tools/v3/assert/cmp"
20 "gotest.tools/v3/internal/format"
21 "gotest.tools/v3/internal/source"
22 )
23
24 func init() {
25 flag.BoolVar(&source.Update, "test.update-golden", false, "deprecated flag")
26 }
27
28 type helperT interface {
29 Helper()
30 }
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 var NormalizeCRLFToLF = os.Getenv("GOTESTTOOLS_GOLDEN_NormalizeCRLFToLF") != "false"
52
53
54 func FlagUpdate() bool {
55 return source.IsUpdate()
56 }
57
58
59 func Open(t assert.TestingT, filename string) *os.File {
60 if ht, ok := t.(helperT); ok {
61 ht.Helper()
62 }
63 f, err := os.Open(Path(filename))
64 assert.NilError(t, err)
65 return f
66 }
67
68
69 func Get(t assert.TestingT, filename string) []byte {
70 if ht, ok := t.(helperT); ok {
71 ht.Helper()
72 }
73 expected, err := os.ReadFile(Path(filename))
74 assert.NilError(t, err)
75 return expected
76 }
77
78
79 func Path(filename string) string {
80 if filepath.IsAbs(filename) {
81 return filename
82 }
83 return filepath.Join("testdata", filename)
84 }
85
86 func removeCarriageReturn(in []byte) []byte {
87 if !NormalizeCRLFToLF {
88 return in
89 }
90 return bytes.Replace(in, []byte("\r\n"), []byte("\n"), -1)
91 }
92
93
94
95
96
97
98
99 func Assert(t assert.TestingT, actual string, filename string, msgAndArgs ...interface{}) {
100 if ht, ok := t.(helperT); ok {
101 ht.Helper()
102 }
103 assert.Assert(t, String(actual, filename), msgAndArgs...)
104 }
105
106
107
108
109
110
111
112
113
114
115
116 func String(actual string, filename string) cmp.Comparison {
117 return func() cmp.Result {
118 actualBytes := removeCarriageReturn([]byte(actual))
119 result, expected := compare(actualBytes, filename)
120 if result != nil {
121 return result
122 }
123 diff := format.UnifiedDiff(format.DiffConfig{
124 A: string(expected),
125 B: string(actualBytes),
126 From: "expected",
127 To: "actual",
128 })
129 return cmp.ResultFailure("\n" + diff + failurePostamble(filename))
130 }
131 }
132
133 func failurePostamble(filename string) string {
134 return fmt.Sprintf(`
135
136 You can run 'go test . -update' to automatically update %s to the new expected value.'
137 `, Path(filename))
138 }
139
140
141
142
143
144
145
146 func AssertBytes(
147 t assert.TestingT,
148 actual []byte,
149 filename string,
150 msgAndArgs ...interface{},
151 ) {
152 if ht, ok := t.(helperT); ok {
153 ht.Helper()
154 }
155 assert.Assert(t, Bytes(actual, filename), msgAndArgs...)
156 }
157
158
159
160
161
162
163 func Bytes(actual []byte, filename string) cmp.Comparison {
164 return func() cmp.Result {
165 result, expected := compare(actual, filename)
166 if result != nil {
167 return result
168 }
169 msg := fmt.Sprintf("%v (actual) != %v (expected)", actual, expected)
170 return cmp.ResultFailure(msg + failurePostamble(filename))
171 }
172 }
173
174 func compare(actual []byte, filename string) (cmp.Result, []byte) {
175 if err := update(filename, actual); err != nil {
176 return cmp.ResultFromError(err), nil
177 }
178 expected, err := os.ReadFile(Path(filename))
179 if err != nil {
180 return cmp.ResultFromError(err), nil
181 }
182 if bytes.Equal(expected, actual) {
183 return cmp.ResultSuccess, nil
184 }
185 return nil, expected
186 }
187
188 func update(filename string, actual []byte) error {
189 if !source.IsUpdate() {
190 return nil
191 }
192 if dir := filepath.Dir(Path(filename)); dir != "." {
193 if err := os.MkdirAll(dir, 0755); err != nil {
194 return err
195 }
196 }
197 return os.WriteFile(Path(filename), actual, 0644)
198 }
199
View as plain text