github.com/golang/review@v0.0.0-20190122205339-266ee1edf5c3/git-codereview/gofmt_test.go (about)

     1  // Copyright 2014 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  	"fmt"
     9  	"io/ioutil"
    10  	"os"
    11  	"strings"
    12  	"testing"
    13  )
    14  
    15  const (
    16  	goodGo      = "package good\n"
    17  	badGo       = " package bad1 "
    18  	badGoFixed  = "package bad1\n"
    19  	bad2Go      = " package bad2 "
    20  	bad2GoFixed = "package bad2\n"
    21  	brokenGo    = "package B R O K E N"
    22  )
    23  
    24  func TestGofmt(t *testing.T) {
    25  	// Test of basic operations.
    26  	gt := newGitTest(t)
    27  	defer gt.done()
    28  
    29  	gt.work(t)
    30  
    31  	if err := os.MkdirAll(gt.client+"/test/bench", 0755); err != nil {
    32  		t.Fatal(err)
    33  	}
    34  	if err := os.MkdirAll(gt.client+"/vendor", 0755); err != nil {
    35  		t.Fatal(err)
    36  	}
    37  	write(t, gt.client+"/bad.go", badGo)
    38  	write(t, gt.client+"/good.go", goodGo)
    39  	write(t, gt.client+"/vendor/bad.go", badGo)
    40  	write(t, gt.client+"/test/bad.go", badGo)
    41  	write(t, gt.client+"/test/good.go", goodGo)
    42  	write(t, gt.client+"/test/bench/bad.go", badGo)
    43  	write(t, gt.client+"/test/bench/good.go", goodGo)
    44  	trun(t, gt.client, "git", "add", ".") // make files tracked
    45  
    46  	testMain(t, "gofmt", "-l")
    47  	testPrintedStdout(t, "bad.go\n", "!good.go", fromSlash("!test/bad"), fromSlash("test/bench/bad.go"), fromSlash("!vendor/bad.go"))
    48  	testMain(t, "gofmt", "-l")
    49  	testPrintedStdout(t, "bad.go\n", "!good.go", fromSlash("!test/bad"), fromSlash("test/bench/bad.go"), fromSlash("!vendor/bad.go"))
    50  
    51  	testMain(t, "gofmt")
    52  	testNoStdout(t)
    53  
    54  	testMain(t, "gofmt", "-l")
    55  	testNoStdout(t)
    56  
    57  	write(t, gt.client+"/bad.go", badGo)
    58  	write(t, gt.client+"/broken.go", brokenGo)
    59  	trun(t, gt.client, "git", "add", ".")
    60  	testMainDied(t, "gofmt", "-l")
    61  	testPrintedStdout(t, "bad.go")
    62  	testPrintedStderr(t, "gofmt reported errors", "broken.go")
    63  }
    64  
    65  func TestGofmtSubdir(t *testing.T) {
    66  	// Check that gofmt prints relative paths for files in or below the current directory.
    67  	gt := newGitTest(t)
    68  	defer gt.done()
    69  
    70  	gt.work(t)
    71  
    72  	mkdir(t, gt.client+"/dir1")
    73  	mkdir(t, gt.client+"/longnamedir2")
    74  	write(t, gt.client+"/dir1/bad1.go", badGo)
    75  	write(t, gt.client+"/longnamedir2/bad2.go", badGo)
    76  	trun(t, gt.client, "git", "add", ".") // make files tracked
    77  
    78  	chdir(t, gt.client)
    79  	testMain(t, "gofmt", "-l")
    80  	testPrintedStdout(t, fromSlash("dir1/bad1.go"), fromSlash("longnamedir2/bad2.go"))
    81  
    82  	chdir(t, gt.client+"/dir1")
    83  	testMain(t, "gofmt", "-l")
    84  	testPrintedStdout(t, "bad1.go", fromSlash("!/bad1.go"), fromSlash("longnamedir2/bad2.go"))
    85  
    86  	chdir(t, gt.client+"/longnamedir2")
    87  	testMain(t, "gofmt", "-l")
    88  	testPrintedStdout(t, "bad2.go", fromSlash("!/bad2.go"), fromSlash("dir1/bad1.go"))
    89  
    90  	mkdir(t, gt.client+"/z")
    91  	chdir(t, gt.client+"/z")
    92  	testMain(t, "gofmt", "-l")
    93  	testPrintedStdout(t, fromSlash("longnamedir2/bad2.go"), fromSlash("dir1/bad1.go"))
    94  }
    95  
    96  func TestGofmtSubdirIndexCheckout(t *testing.T) {
    97  	// Like TestGofmtSubdir but bad Go files are only in index, not working copy.
    98  	// Check also that prints a correct path (relative or absolute) for files outside the
    99  	// current directory, even when running with Git before 2.3.0 which doesn't
   100  	// handle those right in git checkout-index --temp.
   101  
   102  	gt := newGitTest(t)
   103  	defer gt.done()
   104  
   105  	gt.work(t)
   106  
   107  	mkdir(t, gt.client+"/dir1")
   108  	mkdir(t, gt.client+"/longnamedir2")
   109  	write(t, gt.client+"/dir1/bad1.go", badGo)
   110  	write(t, gt.client+"/longnamedir2/bad2.go", badGo)
   111  	trun(t, gt.client, "git", "add", ".") // put files in index
   112  	write(t, gt.client+"/dir1/bad1.go", goodGo)
   113  	write(t, gt.client+"/longnamedir2/bad2.go", goodGo)
   114  
   115  	chdir(t, gt.client)
   116  	testMain(t, "gofmt", "-l")
   117  	testPrintedStdout(t, fromSlash("dir1/bad1.go (staged)"), fromSlash("longnamedir2/bad2.go (staged)"))
   118  
   119  	chdir(t, gt.client+"/dir1")
   120  	testMain(t, "gofmt", "-l")
   121  	testPrintedStdout(t, "bad1.go (staged)", fromSlash("!/bad1.go"), fromSlash("longnamedir2/bad2.go (staged)"))
   122  
   123  	chdir(t, gt.client+"/longnamedir2")
   124  	testMain(t, "gofmt", "-l")
   125  	testPrintedStdout(t, "bad2.go (staged)", fromSlash("!/bad2.go"), fromSlash("dir1/bad1.go (staged)"))
   126  
   127  	mkdir(t, gt.client+"/z")
   128  	chdir(t, gt.client+"/z")
   129  	testMain(t, "gofmt", "-l")
   130  	testPrintedStdout(t, fromSlash("longnamedir2/bad2.go (staged)"), fromSlash("dir1/bad1.go (staged)"))
   131  }
   132  
   133  func TestGofmtUnstaged(t *testing.T) {
   134  	// Test when unstaged files are different from staged ones.
   135  	// See TestHookPreCommitUnstaged for an explanation.
   136  	// In this test we use two different kinds of bad files, so that
   137  	// we can test having a bad file in the index and a different
   138  	// bad file in the working directory.
   139  
   140  	gt := newGitTest(t)
   141  	defer gt.done()
   142  	gt.work(t)
   143  
   144  	name := []string{"good", "bad", "bad2", "broken"}
   145  	orig := []string{goodGo, badGo, bad2Go, brokenGo}
   146  	fixed := []string{goodGo, badGoFixed, bad2GoFixed, brokenGo}
   147  	const N = 4
   148  
   149  	var allFiles, wantOut, wantErr []string
   150  	writeFiles := func(n int) {
   151  		allFiles = nil
   152  		wantOut = nil
   153  		wantErr = nil
   154  		for i := 0; i < N*N*N; i++ {
   155  			// determine n'th digit of 3-digit base-N value i
   156  			j := i
   157  			for k := 0; k < (3 - 1 - n); k++ {
   158  				j /= N
   159  			}
   160  			text := orig[j%N]
   161  			file := fmt.Sprintf("%s-%s-%s.go", name[i/N/N], name[(i/N)%N], name[i%N])
   162  			allFiles = append(allFiles, file)
   163  			write(t, gt.client+"/"+file, text)
   164  
   165  			if (i/N)%N != i%N {
   166  				staged := file + " (staged)"
   167  				switch {
   168  				case strings.Contains(file, "-bad-"), strings.Contains(file, "-bad2-"):
   169  					wantOut = append(wantOut, staged)
   170  					wantErr = append(wantErr, "!"+staged)
   171  				case strings.Contains(file, "-broken-"):
   172  					wantOut = append(wantOut, "!"+staged)
   173  					wantErr = append(wantErr, staged)
   174  				default:
   175  					wantOut = append(wantOut, "!"+staged)
   176  					wantErr = append(wantErr, "!"+staged)
   177  				}
   178  			}
   179  			switch {
   180  			case strings.Contains(file, "-bad.go"), strings.Contains(file, "-bad2.go"):
   181  				if (i/N)%N != i%N {
   182  					file += " (unstaged)"
   183  				}
   184  				wantOut = append(wantOut, file+"\n")
   185  				wantErr = append(wantErr, "!"+file+":", "!"+file+" (unstaged)")
   186  			case strings.Contains(file, "-broken.go"):
   187  				wantOut = append(wantOut, "!"+file+"\n", "!"+file+" (unstaged)")
   188  				wantErr = append(wantErr, file+":")
   189  			default:
   190  				wantOut = append(wantOut, "!"+file+"\n", "!"+file+":", "!"+file+" (unstaged)")
   191  				wantErr = append(wantErr, "!"+file+"\n", "!"+file+":", "!"+file+" (unstaged)")
   192  			}
   193  		}
   194  	}
   195  
   196  	// committed files
   197  	writeFiles(0)
   198  	trun(t, gt.client, "git", "add", ".")
   199  	trun(t, gt.client, "git", "commit", "-m", "msg")
   200  
   201  	// staged files
   202  	writeFiles(1)
   203  	trun(t, gt.client, "git", "add", ".")
   204  
   205  	// unstaged files
   206  	writeFiles(2)
   207  
   208  	// Check that gofmt -l shows the right output and errors.
   209  	testMainDied(t, "gofmt", "-l")
   210  	testPrintedStdout(t, wantOut...)
   211  	testPrintedStderr(t, wantErr...)
   212  
   213  	// Again (last command should not have written anything).
   214  	testMainDied(t, "gofmt", "-l")
   215  	testPrintedStdout(t, wantOut...)
   216  	testPrintedStderr(t, wantErr...)
   217  
   218  	// Reformat in place.
   219  	testMainDied(t, "gofmt")
   220  	testNoStdout(t)
   221  	testPrintedStderr(t, wantErr...)
   222  
   223  	// Read files to make sure unstaged did not bleed into staged.
   224  	for i, file := range allFiles {
   225  		if data, err := ioutil.ReadFile(gt.client + "/" + file); err != nil {
   226  			t.Errorf("%v", err)
   227  		} else if want := fixed[i%N]; string(data) != want {
   228  			t.Errorf("%s: working tree = %q, want %q", file, string(data), want)
   229  		}
   230  		if data, want := trun(t, gt.client, "git", "show", ":"+file), fixed[i/N%N]; data != want {
   231  			t.Errorf("%s: index = %q, want %q", file, data, want)
   232  		}
   233  		if data, want := trun(t, gt.client, "git", "show", "HEAD:"+file), orig[i/N/N]; data != want {
   234  			t.Errorf("%s: commit = %q, want %q", file, data, want)
   235  		}
   236  	}
   237  
   238  	// Check that gofmt -l still shows the errors.
   239  	testMainDied(t, "gofmt", "-l")
   240  	testNoStdout(t)
   241  	testPrintedStderr(t, wantErr...)
   242  }
   243  
   244  func TestGofmtAmbiguousRevision(t *testing.T) {
   245  	gt := newGitTest(t)
   246  	defer gt.done()
   247  
   248  	t.Logf("creating file that conflicts with revision parameter")
   249  	write(t, gt.client+"/HEAD", "foo")
   250  
   251  	testMain(t, "gofmt")
   252  }
   253  
   254  func TestGofmtFastForwardMerge(t *testing.T) {
   255  	gt := newGitTest(t)
   256  	defer gt.done()
   257  
   258  	// merge dev.branch into master
   259  	write(t, gt.server+"/file", "more work")
   260  	trun(t, gt.server, "git", "commit", "-m", "work", "file")
   261  	trun(t, gt.server, "git", "merge", "-m", "merge", "dev.branch")
   262  
   263  	// add bad go file on master
   264  	write(t, gt.server+"/bad.go", "package {\n")
   265  	trun(t, gt.server, "git", "add", "bad.go")
   266  	trun(t, gt.server, "git", "commit", "-m", "bad go")
   267  
   268  	// update client
   269  	trun(t, gt.client, "git", "checkout", "master")
   270  	trun(t, gt.client, "git", "pull")
   271  	testMain(t, "change", "dev.branch")
   272  	trun(t, gt.client, "git", "pull")
   273  
   274  	// merge master into dev.branch, fast forward merge
   275  	trun(t, gt.client, "git", "merge", "--ff-only", "master")
   276  
   277  	// verify that now client is in a state where just the tag is changing; there's no new commit.
   278  	masterHash := strings.TrimSpace(trun(t, gt.server, "git", "rev-parse", "master"))
   279  	devHash := strings.TrimSpace(trun(t, gt.client, "git", "rev-parse", "HEAD"))
   280  
   281  	if masterHash != devHash {
   282  		t.Logf("branches:\n%s", trun(t, gt.client, "git", "branch", "-a", "-v"))
   283  		t.Logf("log:\n%s", trun(t, gt.client, "git", "log", "--graph", "--decorate"))
   284  		t.Fatalf("setup wrong - got different commit hashes on master and dev branch")
   285  	}
   286  
   287  	// check that gofmt finds nothing to do, ignoring the bad (but committed) file1.go.
   288  	testMain(t, "gofmt")
   289  	testNoStdout(t)
   290  	testNoStderr(t)
   291  }