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 func runTest(t *testing.T, in, out string) {
58
59 *simplifyAST = false
60 *rewriteRule = ""
61 info, err := os.Lstat(in)
62 if err != nil {
63 t.Error(err)
64 return
65 }
66 for _, flag := range strings.Split(gofmtFlags(in, 20), " ") {
67 elts := strings.SplitN(flag, "=", 2)
68 name := elts[0]
69 value := ""
70 if len(elts) == 2 {
71 value = elts[1]
72 }
73 switch name {
74 case "":
75
76 case "-r":
77 *rewriteRule = value
78 case "-s":
79 *simplifyAST = true
80 case "-stdin":
81
82 info = nil
83 default:
84 t.Errorf("unrecognized flag name: %s", name)
85 }
86 }
87
88 initParserMode()
89 initRewrite()
90
91 const maxWeight = 2 << 20
92 var buf, errBuf bytes.Buffer
93 s := newSequencer(maxWeight, &buf, &errBuf)
94 s.Add(fileWeight(in, info), func(r *reporter) error {
95 return processFile(in, info, nil, r)
96 })
97 if errBuf.Len() > 0 {
98 t.Logf("%q", errBuf.Bytes())
99 }
100 if s.GetExitCode() != 0 {
101 t.Fail()
102 }
103
104 expected, err := os.ReadFile(out)
105 if err != nil {
106 t.Error(err)
107 return
108 }
109
110 if got := buf.Bytes(); !bytes.Equal(got, expected) {
111 if *update {
112 if in != out {
113 if err := os.WriteFile(out, got, 0666); err != nil {
114 t.Error(err)
115 }
116 return
117 }
118
119 t.Errorf("WARNING: -update did not rewrite input file %s", in)
120 }
121
122 t.Errorf("(gofmt %s) != %s (see %s.gofmt)", in, out, in)
123 d, err := diffWithReplaceTempFile(expected, got, in)
124 if err == nil {
125 t.Errorf("%s", d)
126 }
127 if err := os.WriteFile(in+".gofmt", got, 0666); err != nil {
128 t.Error(err)
129 }
130 }
131 }
132
133
134
135
136
137
138
139
140 func TestRewrite(t *testing.T) {
141
142 match, err := filepath.Glob("testdata/*.input")
143 if err != nil {
144 t.Fatal(err)
145 }
146
147
148 match = append(match, "gofmt.go", "gofmt_test.go")
149
150 for _, in := range match {
151 out := in
152 if strings.HasSuffix(in, ".input") {
153 out = in[:len(in)-len(".input")] + ".golden"
154 }
155 runTest(t, in, out)
156 if in != out {
157
158 runTest(t, out, out)
159 }
160 }
161 }
162
163
164 func TestCRLF(t *testing.T) {
165 const input = "testdata/crlf.input"
166 const golden = "testdata/crlf.golden"
167
168 data, err := os.ReadFile(input)
169 if err != nil {
170 t.Error(err)
171 }
172 if !bytes.Contains(data, []byte("\r\n")) {
173 t.Errorf("%s contains no CR/LF's", input)
174 }
175
176 data, err = os.ReadFile(golden)
177 if err != nil {
178 t.Error(err)
179 }
180 if bytes.Contains(data, []byte("\r")) {
181 t.Errorf("%s contains CR's", golden)
182 }
183 }
184
185 func TestBackupFile(t *testing.T) {
186 dir, err := os.MkdirTemp("", "gofmt_test")
187 if err != nil {
188 t.Fatal(err)
189 }
190 defer os.RemoveAll(dir)
191 name, err := backupFile(filepath.Join(dir, "foo.go"), []byte(" package main"), 0644)
192 if err != nil {
193 t.Fatal(err)
194 }
195 t.Logf("Created: %s", name)
196 }
197
198 func TestDiff(t *testing.T) {
199 if _, err := exec.LookPath("diff"); err != nil {
200 t.Skipf("skip test on %s: diff command is required", runtime.GOOS)
201 }
202 in := []byte("first\nsecond\n")
203 out := []byte("first\nthird\n")
204 filename := "difftest.txt"
205 b, err := diffWithReplaceTempFile(in, out, filename)
206 if err != nil {
207 t.Fatal(err)
208 }
209
210 if runtime.GOOS == "windows" {
211 b = bytes.ReplaceAll(b, []byte{'\r', '\n'}, []byte{'\n'})
212 }
213
214 bs := bytes.SplitN(b, []byte{'\n'}, 3)
215 line0, line1 := bs[0], bs[1]
216
217 if prefix := "--- difftest.txt.orig"; !bytes.HasPrefix(line0, []byte(prefix)) {
218 t.Errorf("diff: first line should start with `%s`\ngot: %s", prefix, line0)
219 }
220
221 if prefix := "+++ difftest.txt"; !bytes.HasPrefix(line1, []byte(prefix)) {
222 t.Errorf("diff: second line should start with `%s`\ngot: %s", prefix, line1)
223 }
224
225 want := `@@ -1,2 +1,2 @@
226 first
227 -second
228 +third
229 `
230
231 if got := string(bs[2]); got != want {
232 t.Errorf("diff: got:\n%s\nwant:\n%s", got, want)
233 }
234 }
235
236 func TestReplaceTempFilename(t *testing.T) {
237 diff := []byte(`--- /tmp/tmpfile1 2017-02-08 00:53:26.175105619 +0900
238 +++ /tmp/tmpfile2 2017-02-08 00:53:38.415151275 +0900
239 @@ -1,2 +1,2 @@
240 first
241 -second
242 +third
243 `)
244 want := []byte(`--- path/to/file.go.orig 2017-02-08 00:53:26.175105619 +0900
245 +++ path/to/file.go 2017-02-08 00:53:38.415151275 +0900
246 @@ -1,2 +1,2 @@
247 first
248 -second
249 +third
250 `)
251
252
253 sep := string(os.PathSeparator)
254 filename := strings.Join([]string{"path", "to", "file.go"}, sep)
255 got, err := replaceTempFilename(diff, filename)
256 if err != nil {
257 t.Fatal(err)
258 }
259 if !bytes.Equal(got, want) {
260 t.Errorf("os.PathSeparator='%s': replacedDiff:\ngot:\n%s\nwant:\n%s", sep, got, want)
261 }
262 }
263
View as plain text