github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/go/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  		// A known instance of gofmt not being idempotent
    89  		// (see Issue #24472)
    90  		if strings.HasSuffix(filename, "issue22662.go") {
    91  			t.Log("known gofmt idempotency bug (Issue #24472)")
    92  			return
    93  		}
    94  		t.Errorf("gofmt %s not idempotent", filename)
    95  	}
    96  }
    97  
    98  func testFiles(t *testing.T, filenames <-chan string, done chan<- int) {
    99  	b1 := new(bytes.Buffer)
   100  	b2 := new(bytes.Buffer)
   101  	for filename := range filenames {
   102  		testFile(t, b1, b2, filename)
   103  	}
   104  	done <- 0
   105  }
   106  
   107  func genFilenames(t *testing.T, filenames chan<- string) {
   108  	defer close(filenames)
   109  
   110  	handleFile := func(filename string, fi os.FileInfo, err error) error {
   111  		if err != nil {
   112  			t.Error(err)
   113  			return nil
   114  		}
   115  		if isGoFile(fi) {
   116  			filenames <- filename
   117  			nfiles++
   118  		}
   119  		return nil
   120  	}
   121  
   122  	// test Go files provided via -files, if any
   123  	if *files != "" {
   124  		for _, filename := range strings.Split(*files, ",") {
   125  			fi, err := os.Stat(filename)
   126  			handleFile(filename, fi, err)
   127  		}
   128  		return // ignore files under -root
   129  	}
   130  
   131  	// otherwise, test all Go files under *root
   132  	filepath.Walk(*root, handleFile)
   133  }
   134  
   135  func TestAll(t *testing.T) {
   136  	if testing.Short() {
   137  		return
   138  	}
   139  
   140  	if *ngo < 1 {
   141  		*ngo = 1 // make sure test is run
   142  	}
   143  	if *verbose {
   144  		fmt.Printf("running test using %d goroutines\n", *ngo)
   145  	}
   146  
   147  	// generate filenames
   148  	filenames := make(chan string, 32)
   149  	go genFilenames(t, filenames)
   150  
   151  	// launch test goroutines
   152  	done := make(chan int)
   153  	for i := 0; i < *ngo; i++ {
   154  		go testFiles(t, filenames, done)
   155  	}
   156  
   157  	// wait for all test goroutines to complete
   158  	for i := 0; i < *ngo; i++ {
   159  		<-done
   160  	}
   161  
   162  	if *verbose {
   163  		fmt.Printf("processed %d files\n", nfiles)
   164  	}
   165  }