github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/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  	"path/filepath"
    13  	"strings"
    14  	"testing"
    15  	"text/scanner"
    16  )
    17  
    18  var update = flag.Bool("update", false, "update .golden files")
    19  
    20  // gofmtFlags looks for a comment of the form
    21  //
    22  //	//gofmt flags
    23  //
    24  // within the first maxLines lines of the given file,
    25  // and returns the flags string, if any. Otherwise it
    26  // returns the empty string.
    27  func gofmtFlags(filename string, maxLines int) string {
    28  	f, err := os.Open(filename)
    29  	if err != nil {
    30  		return "" // ignore errors - they will be found later
    31  	}
    32  	defer f.Close()
    33  
    34  	// initialize scanner
    35  	var s scanner.Scanner
    36  	s.Init(f)
    37  	s.Error = func(*scanner.Scanner, string) {}       // ignore errors
    38  	s.Mode = scanner.GoTokens &^ scanner.SkipComments // want comments
    39  
    40  	// look for //gofmt comment
    41  	for s.Line <= maxLines {
    42  		switch s.Scan() {
    43  		case scanner.Comment:
    44  			const prefix = "//gofmt "
    45  			if t := s.TokenText(); strings.HasPrefix(t, prefix) {
    46  				return strings.TrimSpace(t[len(prefix):])
    47  			}
    48  		case scanner.EOF:
    49  			return ""
    50  		}
    51  
    52  	}
    53  
    54  	return ""
    55  }
    56  
    57  func runTest(t *testing.T, in, out string) {
    58  	// process flags
    59  	*simplifyAST = false
    60  	*rewriteRule = ""
    61  	stdin := false
    62  	for _, flag := range strings.Split(gofmtFlags(in, 20), " ") {
    63  		elts := strings.SplitN(flag, "=", 2)
    64  		name := elts[0]
    65  		value := ""
    66  		if len(elts) == 2 {
    67  			value = elts[1]
    68  		}
    69  		switch name {
    70  		case "":
    71  			// no flags
    72  		case "-r":
    73  			*rewriteRule = value
    74  		case "-s":
    75  			*simplifyAST = true
    76  		case "-stdin":
    77  			// fake flag - pretend input is from stdin
    78  			stdin = true
    79  		default:
    80  			t.Errorf("unrecognized flag name: %s", name)
    81  		}
    82  	}
    83  
    84  	initParserMode()
    85  	initRewrite()
    86  
    87  	var buf bytes.Buffer
    88  	err := processFile(in, nil, &buf, stdin)
    89  	if err != nil {
    90  		t.Error(err)
    91  		return
    92  	}
    93  
    94  	expected, err := ioutil.ReadFile(out)
    95  	if err != nil {
    96  		t.Error(err)
    97  		return
    98  	}
    99  
   100  	if got := buf.Bytes(); !bytes.Equal(got, expected) {
   101  		if *update {
   102  			if in != out {
   103  				if err := ioutil.WriteFile(out, got, 0666); err != nil {
   104  					t.Error(err)
   105  				}
   106  				return
   107  			}
   108  			// in == out: don't accidentally destroy input
   109  			t.Errorf("WARNING: -update did not rewrite input file %s", in)
   110  		}
   111  
   112  		t.Errorf("(gofmt %s) != %s (see %s.gofmt)", in, out, in)
   113  		d, err := diff(expected, got)
   114  		if err == nil {
   115  			t.Errorf("%s", d)
   116  		}
   117  		if err := ioutil.WriteFile(in+".gofmt", got, 0666); err != nil {
   118  			t.Error(err)
   119  		}
   120  	}
   121  }
   122  
   123  // TestRewrite processes testdata/*.input files and compares them to the
   124  // corresponding testdata/*.golden files. The gofmt flags used to process
   125  // a file must be provided via a comment of the form
   126  //
   127  //	//gofmt flags
   128  //
   129  // in the processed file within the first 20 lines, if any.
   130  func TestRewrite(t *testing.T) {
   131  	// determine input files
   132  	match, err := filepath.Glob("testdata/*.input")
   133  	if err != nil {
   134  		t.Fatal(err)
   135  	}
   136  
   137  	// add larger examples
   138  	match = append(match, "gofmt.go", "gofmt_test.go")
   139  
   140  	for _, in := range match {
   141  		out := in // for files where input and output are identical
   142  		if strings.HasSuffix(in, ".input") {
   143  			out = in[:len(in)-len(".input")] + ".golden"
   144  		}
   145  		runTest(t, in, out)
   146  		if in != out {
   147  			// Check idempotence.
   148  			runTest(t, out, out)
   149  		}
   150  	}
   151  }
   152  
   153  // Test case for issue 3961.
   154  func TestCRLF(t *testing.T) {
   155  	const input = "testdata/crlf.input"   // must contain CR/LF's
   156  	const golden = "testdata/crlf.golden" // must not contain any CR's
   157  
   158  	data, err := ioutil.ReadFile(input)
   159  	if err != nil {
   160  		t.Error(err)
   161  	}
   162  	if bytes.Index(data, []byte("\r\n")) < 0 {
   163  		t.Errorf("%s contains no CR/LF's", input)
   164  	}
   165  
   166  	data, err = ioutil.ReadFile(golden)
   167  	if err != nil {
   168  		t.Error(err)
   169  	}
   170  	if bytes.Index(data, []byte("\r")) >= 0 {
   171  		t.Errorf("%s contains CR's", golden)
   172  	}
   173  }