github.com/sbinet/go@v0.0.0-20160827155028-54d7de7dd62b/src/cmd/gofmt/long_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 // This test applies gofmt to all Go files under -root. 6 // To test specific files provide a list of comma-separated 7 // filenames via the -files flag: go test -files=gofmt.go . 8 9 package main 10 11 import ( 12 "bytes" 13 "flag" 14 "fmt" 15 "go/ast" 16 "go/printer" 17 "go/token" 18 "io" 19 "os" 20 "path/filepath" 21 "runtime" 22 "strings" 23 "testing" 24 ) 25 26 var ( 27 root = flag.String("root", runtime.GOROOT(), "test root directory") 28 files = flag.String("files", "", "comma-separated list of files to test") 29 ngo = flag.Int("n", runtime.NumCPU(), "number of goroutines used") 30 verbose = flag.Bool("verbose", false, "verbose mode") 31 nfiles int // number of files processed 32 ) 33 34 func gofmt(fset *token.FileSet, filename string, src *bytes.Buffer) error { 35 f, _, _, err := parse(fset, filename, src.Bytes(), false) 36 if err != nil { 37 return err 38 } 39 ast.SortImports(fset, f) 40 src.Reset() 41 return (&printer.Config{Mode: printerMode, Tabwidth: tabWidth}).Fprint(src, fset, f) 42 } 43 44 func testFile(t *testing.T, b1, b2 *bytes.Buffer, filename string) { 45 // open file 46 f, err := os.Open(filename) 47 if err != nil { 48 t.Error(err) 49 return 50 } 51 52 // read file 53 b1.Reset() 54 _, err = io.Copy(b1, f) 55 f.Close() 56 if err != nil { 57 t.Error(err) 58 return 59 } 60 61 // exclude files w/ syntax errors (typically test cases) 62 fset := token.NewFileSet() 63 if _, _, _, err = parse(fset, filename, b1.Bytes(), false); err != nil { 64 if *verbose { 65 fmt.Fprintf(os.Stderr, "ignoring %s\n", err) 66 } 67 return 68 } 69 70 // gofmt file 71 if err = gofmt(fset, filename, b1); err != nil { 72 t.Errorf("1st gofmt failed: %v", err) 73 return 74 } 75 76 // make a copy of the result 77 b2.Reset() 78 b2.Write(b1.Bytes()) 79 80 // gofmt result again 81 if err = gofmt(fset, filename, b2); err != nil { 82 t.Errorf("2nd gofmt failed: %v", err) 83 return 84 } 85 86 // the first and 2nd result should be identical 87 if !bytes.Equal(b1.Bytes(), b2.Bytes()) { 88 t.Errorf("gofmt %s not idempotent", filename) 89 } 90 } 91 92 func testFiles(t *testing.T, filenames <-chan string, done chan<- int) { 93 b1 := new(bytes.Buffer) 94 b2 := new(bytes.Buffer) 95 for filename := range filenames { 96 testFile(t, b1, b2, filename) 97 } 98 done <- 0 99 } 100 101 func genFilenames(t *testing.T, filenames chan<- string) { 102 defer close(filenames) 103 104 handleFile := func(filename string, fi os.FileInfo, err error) error { 105 if err != nil { 106 t.Error(err) 107 return nil 108 } 109 if isGoFile(fi) { 110 filenames <- filename 111 nfiles++ 112 } 113 return nil 114 } 115 116 // test Go files provided via -files, if any 117 if *files != "" { 118 for _, filename := range strings.Split(*files, ",") { 119 fi, err := os.Stat(filename) 120 handleFile(filename, fi, err) 121 } 122 return // ignore files under -root 123 } 124 125 // otherwise, test all Go files under *root 126 filepath.Walk(*root, handleFile) 127 } 128 129 func TestAll(t *testing.T) { 130 if testing.Short() { 131 return 132 } 133 134 if *ngo < 1 { 135 *ngo = 1 // make sure test is run 136 } 137 if *verbose { 138 fmt.Printf("running test using %d goroutines\n", *ngo) 139 } 140 141 // generate filenames 142 filenames := make(chan string, 32) 143 go genFilenames(t, filenames) 144 145 // launch test goroutines 146 done := make(chan int) 147 for i := 0; i < *ngo; i++ { 148 go testFiles(t, filenames, done) 149 } 150 151 // wait for all test goroutines to complete 152 for i := 0; i < *ngo; i++ { 153 <-done 154 } 155 156 if *verbose { 157 fmt.Printf("processed %d files\n", nfiles) 158 } 159 }