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