github.com/ActiveState/go@v0.0.0-20170614201249-0b81c023a722/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  }