Source file
src/cmd/gofmt/gofmt_test.go
1
2
3
4
5 package main
6
7 import (
8 "bytes"
9 "flag"
10 "os"
11 "os/exec"
12 "path/filepath"
13 "runtime"
14 "strings"
15 "testing"
16 "text/scanner"
17 )
18
19 var update = flag.Bool("update", false, "update .golden files")
20
21
22
23
24
25
26
27
28 func gofmtFlags(filename string, maxLines int) string {
29 f, err := os.Open(filename)
30 if err != nil {
31 return ""
32 }
33 defer f.Close()
34
35
36 var s scanner.Scanner
37 s.Init(f)
38 s.Error = func(*scanner.Scanner, string) {}
39 s.Mode = scanner.GoTokens &^ scanner.SkipComments
40
41
42 for s.Line <= maxLines {
43 switch s.Scan() {
44 case scanner.Comment:
45 const prefix = "//gofmt "
46 if t := s.TokenText(); strings.HasPrefix(t, prefix) {
47 return strings.TrimSpace(t[len(prefix):])
48 }
49 case scanner.EOF:
50 return ""
51 }
52 }
53
54 return ""
55 }
56
57 var typeParamsEnabled = false
58
59 func runTest(t *testing.T, in, out string) {
60
61 *simplifyAST = false
62 *rewriteRule = ""
63 stdin := false
64 for _, flag := range strings.Split(gofmtFlags(in, 20), " ") {
65 elts := strings.SplitN(flag, "=", 2)
66 name := elts[0]
67 value := ""
68 if len(elts) == 2 {
69 value = elts[1]
70 }
71 switch name {
72 case "":
73
74 case "-r":
75 *rewriteRule = value
76 case "-s":
77 *simplifyAST = true
78 case "-stdin":
79
80 stdin = true
81 case "-G":
82
83 if !typeParamsEnabled {
84 return
85 }
86 default:
87 t.Errorf("unrecognized flag name: %s", name)
88 }
89 }
90
91 initParserMode()
92 initRewrite()
93
94 var buf bytes.Buffer
95 err := processFile(in, nil, &buf, stdin)
96 if err != nil {
97 t.Error(err)
98 return
99 }
100
101 expected, err := os.ReadFile(out)
102 if err != nil {
103 t.Error(err)
104 return
105 }
106
107 if got := buf.Bytes(); !bytes.Equal(got, expected) {
108 if *update {
109 if in != out {
110 if err := os.WriteFile(out, got, 0666); err != nil {
111 t.Error(err)
112 }
113 return
114 }
115
116 t.Errorf("WARNING: -update did not rewrite input file %s", in)
117 }
118
119 t.Errorf("(gofmt %s) != %s (see %s.gofmt)", in, out, in)
120 d, err := diffWithReplaceTempFile(expected, got, in)
121 if err == nil {
122 t.Errorf("%s", d)
123 }
124 if err := os.WriteFile(in+".gofmt", got, 0666); err != nil {
125 t.Error(err)
126 }
127 }
128 }
129
130
131
132
133
134
135
136
137 func TestRewrite(t *testing.T) {
138
139 match, err := filepath.Glob("testdata/*.input")
140 if err != nil {
141 t.Fatal(err)
142 }
143
144
145 match = append(match, "gofmt.go", "gofmt_test.go")
146
147 for _, in := range match {
148 out := in
149 if strings.HasSuffix(in, ".input") {
150 out = in[:len(in)-len(".input")] + ".golden"
151 }
152 runTest(t, in, out)
153 if in != out {
154
155 runTest(t, out, out)
156 }
157 }
158 }
159
160
161 func TestCRLF(t *testing.T) {
162 const input = "testdata/crlf.input"
163 const golden = "testdata/crlf.golden"
164
165 data, err := os.ReadFile(input)
166 if err != nil {
167 t.Error(err)
168 }
169 if !bytes.Contains(data, []byte("\r\n")) {
170 t.Errorf("%s contains no CR/LF's", input)
171 }
172
173 data, err = os.ReadFile(golden)
174 if err != nil {
175 t.Error(err)
176 }
177 if bytes.Contains(data, []byte("\r")) {
178 t.Errorf("%s contains CR's", golden)
179 }
180 }
181
182 func TestBackupFile(t *testing.T) {
183 dir, err := os.MkdirTemp("", "gofmt_test")
184 if err != nil {
185 t.Fatal(err)
186 }
187 defer os.RemoveAll(dir)
188 name, err := backupFile(filepath.Join(dir, "foo.go"), []byte(" package main"), 0644)
189 if err != nil {
190 t.Fatal(err)
191 }
192 t.Logf("Created: %s", name)
193 }
194
195 func TestDiff(t *testing.T) {
196 if _, err := exec.LookPath("diff"); err != nil {
197 t.Skipf("skip test on %s: diff command is required", runtime.GOOS)
198 }
199 in := []byte("first\nsecond\n")
200 out := []byte("first\nthird\n")
201 filename := "difftest.txt"
202 b, err := diffWithReplaceTempFile(in, out, filename)
203 if err != nil {
204 t.Fatal(err)
205 }
206
207 if runtime.GOOS == "windows" {
208 b = bytes.ReplaceAll(b, []byte{'\r', '\n'}, []byte{'\n'})
209 }
210
211 bs := bytes.SplitN(b, []byte{'\n'}, 3)
212 line0, line1 := bs[0], bs[1]
213
214 if prefix := "--- difftest.txt.orig"; !bytes.HasPrefix(line0, []byte(prefix)) {
215 t.Errorf("diff: first line should start with `%s`\ngot: %s", prefix, line0)
216 }
217
218 if prefix := "+++ difftest.txt"; !bytes.HasPrefix(line1, []byte(prefix)) {
219 t.Errorf("diff: second line should start with `%s`\ngot: %s", prefix, line1)
220 }
221
222 want := `@@ -1,2 +1,2 @@
223 first
224 -second
225 +third
226 `
227
228 if got := string(bs[2]); got != want {
229 t.Errorf("diff: got:\n%s\nwant:\n%s", got, want)
230 }
231 }
232
233 func TestReplaceTempFilename(t *testing.T) {
234 diff := []byte(`--- /tmp/tmpfile1 2017-02-08 00:53:26.175105619 +0900
235 +++ /tmp/tmpfile2 2017-02-08 00:53:38.415151275 +0900
236 @@ -1,2 +1,2 @@
237 first
238 -second
239 +third
240 `)
241 want := []byte(`--- path/to/file.go.orig 2017-02-08 00:53:26.175105619 +0900
242 +++ path/to/file.go 2017-02-08 00:53:38.415151275 +0900
243 @@ -1,2 +1,2 @@
244 first
245 -second
246 +third
247 `)
248
249
250 sep := string(os.PathSeparator)
251 filename := strings.Join([]string{"path", "to", "file.go"}, sep)
252 got, err := replaceTempFilename(diff, filename)
253 if err != nil {
254 t.Fatal(err)
255 }
256 if !bytes.Equal(got, want) {
257 t.Errorf("os.PathSeparator='%s': replacedDiff:\ngot:\n%s\nwant:\n%s", sep, got, want)
258 }
259 }
260
View as plain text