github.com/likebike/go--@v0.0.0-20190911215757-0bd925d16e96/go/src/cmd/gofmt/gofmt_test.go (about) 1 // Copyright 2011 The Go 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 main 6 7 import ( 8 "bytes" 9 "flag" 10 "io/ioutil" 11 "os" 12 "os/exec" 13 "path/filepath" 14 "runtime" 15 "strings" 16 "testing" 17 "text/scanner" 18 ) 19 20 var update = flag.Bool("update", false, "update .golden files") 21 22 // gofmtFlags looks for a comment of the form 23 // 24 // //gofmt flags 25 // 26 // within the first maxLines lines of the given file, 27 // and returns the flags string, if any. Otherwise it 28 // returns the empty string. 29 func gofmtFlags(filename string, maxLines int) string { 30 f, err := os.Open(filename) 31 if err != nil { 32 return "" // ignore errors - they will be found later 33 } 34 defer f.Close() 35 36 // initialize scanner 37 var s scanner.Scanner 38 s.Init(f) 39 s.Error = func(*scanner.Scanner, string) {} // ignore errors 40 s.Mode = scanner.GoTokens &^ scanner.SkipComments // want comments 41 42 // look for //gofmt comment 43 for s.Line <= maxLines { 44 switch s.Scan() { 45 case scanner.Comment: 46 const prefix = "//gofmt " 47 if t := s.TokenText(); strings.HasPrefix(t, prefix) { 48 return strings.TrimSpace(t[len(prefix):]) 49 } 50 case scanner.EOF: 51 return "" 52 } 53 54 } 55 56 return "" 57 } 58 59 func runTest(t *testing.T, in, out string) { 60 // process flags 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 // no flags 74 case "-r": 75 *rewriteRule = value 76 case "-s": 77 *simplifyAST = true 78 case "-stdin": 79 // fake flag - pretend input is from stdin 80 stdin = true 81 default: 82 t.Errorf("unrecognized flag name: %s", name) 83 } 84 } 85 86 initParserMode() 87 initRewrite() 88 89 var buf bytes.Buffer 90 err := processFile(in, nil, &buf, stdin) 91 if err != nil { 92 t.Error(err) 93 return 94 } 95 96 expected, err := ioutil.ReadFile(out) 97 if err != nil { 98 t.Error(err) 99 return 100 } 101 102 if got := buf.Bytes(); !bytes.Equal(got, expected) { 103 if *update { 104 if in != out { 105 if err := ioutil.WriteFile(out, got, 0666); err != nil { 106 t.Error(err) 107 } 108 return 109 } 110 // in == out: don't accidentally destroy input 111 t.Errorf("WARNING: -update did not rewrite input file %s", in) 112 } 113 114 t.Errorf("(gofmt %s) != %s (see %s.gofmt)", in, out, in) 115 d, err := diff(expected, got, in) 116 if err == nil { 117 t.Errorf("%s", d) 118 } 119 if err := ioutil.WriteFile(in+".gofmt", got, 0666); err != nil { 120 t.Error(err) 121 } 122 } 123 } 124 125 // TestRewrite processes testdata/*.input files and compares them to the 126 // corresponding testdata/*.golden files. The gofmt flags used to process 127 // a file must be provided via a comment of the form 128 // 129 // //gofmt flags 130 // 131 // in the processed file within the first 20 lines, if any. 132 func TestRewrite(t *testing.T) { 133 // determine input files 134 match, err := filepath.Glob("testdata/*.input") 135 if err != nil { 136 t.Fatal(err) 137 } 138 139 // add larger examples 140 match = append(match, "gofmt.go", "gofmt_test.go") 141 142 for _, in := range match { 143 out := in // for files where input and output are identical 144 if strings.HasSuffix(in, ".input") { 145 out = in[:len(in)-len(".input")] + ".golden" 146 } 147 runTest(t, in, out) 148 if in != out { 149 // Check idempotence. 150 runTest(t, out, out) 151 } 152 } 153 } 154 155 // Test case for issue 3961. 156 func TestCRLF(t *testing.T) { 157 const input = "testdata/crlf.input" // must contain CR/LF's 158 const golden = "testdata/crlf.golden" // must not contain any CR's 159 160 data, err := ioutil.ReadFile(input) 161 if err != nil { 162 t.Error(err) 163 } 164 if !bytes.Contains(data, []byte("\r\n")) { 165 t.Errorf("%s contains no CR/LF's", input) 166 } 167 168 data, err = ioutil.ReadFile(golden) 169 if err != nil { 170 t.Error(err) 171 } 172 if bytes.Contains(data, []byte("\r")) { 173 t.Errorf("%s contains CR's", golden) 174 } 175 } 176 177 func TestBackupFile(t *testing.T) { 178 dir, err := ioutil.TempDir("", "gofmt_test") 179 if err != nil { 180 t.Fatal(err) 181 } 182 defer os.RemoveAll(dir) 183 name, err := backupFile(filepath.Join(dir, "foo.go"), []byte(" package main"), 0644) 184 if err != nil { 185 t.Fatal(err) 186 } 187 t.Logf("Created: %s", name) 188 } 189 190 func TestDiff(t *testing.T) { 191 if _, err := exec.LookPath("diff"); err != nil { 192 t.Skipf("skip test on %s: diff command is required", runtime.GOOS) 193 } 194 in := []byte("first\nsecond\n") 195 out := []byte("first\nthird\n") 196 filename := "difftest.txt" 197 b, err := diff(in, out, filename) 198 if err != nil { 199 t.Fatal(err) 200 } 201 202 if runtime.GOOS == "windows" { 203 b = bytes.Replace(b, []byte{'\r', '\n'}, []byte{'\n'}, -1) 204 } 205 206 bs := bytes.SplitN(b, []byte{'\n'}, 3) 207 line0, line1 := bs[0], bs[1] 208 209 if prefix := "--- difftest.txt.orig"; !bytes.HasPrefix(line0, []byte(prefix)) { 210 t.Errorf("diff: first line should start with `%s`\ngot: %s", prefix, line0) 211 } 212 213 if prefix := "+++ difftest.txt"; !bytes.HasPrefix(line1, []byte(prefix)) { 214 t.Errorf("diff: second line should start with `%s`\ngot: %s", prefix, line1) 215 } 216 217 want := `@@ -1,2 +1,2 @@ 218 first 219 -second 220 +third 221 ` 222 223 if got := string(bs[2]); got != want { 224 t.Errorf("diff: got:\n%s\nwant:\n%s", got, want) 225 } 226 } 227 228 func TestReplaceTempFilename(t *testing.T) { 229 diff := []byte(`--- /tmp/tmpfile1 2017-02-08 00:53:26.175105619 +0900 230 +++ /tmp/tmpfile2 2017-02-08 00:53:38.415151275 +0900 231 @@ -1,2 +1,2 @@ 232 first 233 -second 234 +third 235 `) 236 want := []byte(`--- path/to/file.go.orig 2017-02-08 00:53:26.175105619 +0900 237 +++ path/to/file.go 2017-02-08 00:53:38.415151275 +0900 238 @@ -1,2 +1,2 @@ 239 first 240 -second 241 +third 242 `) 243 // Check path in diff output is always slash regardless of the 244 // os.PathSeparator (`/` or `\`). 245 sep := string(os.PathSeparator) 246 filename := strings.Join([]string{"path", "to", "file.go"}, sep) 247 got, err := replaceTempFilename(diff, filename) 248 if err != nil { 249 t.Fatal(err) 250 } 251 if !bytes.Equal(got, want) { 252 t.Errorf("os.PathSeparator='%s': replacedDiff:\ngot:\n%s\nwant:\n%s", sep, got, want) 253 } 254 }