github.com/kekek/gb@v0.4.5-0.20170222120241-d4ba64b0b297/cmd/gb/gb_test.go (about)

     1  // Copyright 2015 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_test
     6  
     7  // gb functional tests adapted from src/cmd/go/go_test.go
     8  
     9  import (
    10  	"bytes"
    11  	"flag"
    12  	"fmt"
    13  	"go/format"
    14  	"io"
    15  	"io/ioutil"
    16  	"log"
    17  	"os"
    18  	"os/exec"
    19  	"path/filepath"
    20  	"regexp"
    21  	"runtime"
    22  	"strings"
    23  	"testing"
    24  )
    25  
    26  var (
    27  	canRun  = true  // whether we can run go or ./testgb
    28  	canRace = false // whether we can run the race detector
    29  
    30  	exeSuffix string // ".exe" on Windows
    31  
    32  	testgb string = "testgb"
    33  )
    34  
    35  func init() {
    36  	switch runtime.GOOS {
    37  	case "android", "nacl":
    38  		canRun = false
    39  	case "darwin":
    40  		switch runtime.GOARCH {
    41  		case "arm", "arm64":
    42  			canRun = false
    43  		}
    44  	}
    45  
    46  	switch runtime.GOOS {
    47  	case "windows":
    48  		exeSuffix = ".exe"
    49  	}
    50  	testgb += exeSuffix
    51  }
    52  
    53  // The TestMain function creates a gb command for testing purposes and
    54  // deletes it after the tests have been run.
    55  func TestMain(m *testing.M) {
    56  	flag.Parse()
    57  
    58  	if canRun {
    59  		dir, err := ioutil.TempDir("", "testgb")
    60  		if err != nil {
    61  			fmt.Fprintf(os.Stderr, "cannot create temporary directory: %v", err)
    62  			os.Exit(2)
    63  		}
    64  		testgb = filepath.Join(dir, testgb)
    65  		locations := [][]string{
    66  			{runtime.GOROOT(), "bin", "go"},
    67  			{runtime.GOROOT(), "..", "bin", "go"},
    68  			{runtime.GOROOT(), "..", "..", "bin", "go"},
    69  		}
    70  		ok := false
    71  		for _, loc := range locations {
    72  			out, err := exec.Command(filepath.Join(loc...), "build", "-o", testgb).CombinedOutput()
    73  			if err == nil {
    74  				ok = true
    75  				break
    76  			}
    77  			log.Printf("building testgb failed: %v\n%s", err, out)
    78  		}
    79  		if !ok {
    80  			os.Exit(2)
    81  		}
    82  		_, err = os.Stat(filepath.Join(runtime.GOROOT(), "pkg", fmt.Sprintf("%s_%s_race", runtime.GOOS, runtime.GOARCH), "runtime.a"))
    83  		switch {
    84  		case os.IsNotExist(err):
    85  			log.Printf("go installation at %s is missing race support", runtime.GOROOT())
    86  		case runtime.GOARCH == "amd64":
    87  			canRace = runtime.GOOS == "linux" || runtime.GOOS == "freebsd" || runtime.GOOS == "windows" || runtime.GOOS == "darwin"
    88  		}
    89  	}
    90  
    91  	// Don't let these environment variables confuse the test.
    92  	os.Unsetenv("GOBIN")
    93  	os.Unsetenv("GOPATH")
    94  	os.Unsetenv("DEBUG")
    95  
    96  	r := m.Run()
    97  	os.Exit(r)
    98  }
    99  
   100  // T manage a single run of the testgb binary.
   101  type T struct {
   102  	*testing.T
   103  	temps          []string
   104  	wd             string
   105  	env            []string
   106  	tempdir        string
   107  	ran            bool
   108  	stdin          io.Reader
   109  	stdout, stderr bytes.Buffer
   110  }
   111  
   112  // must gives a fatal error if err is not nil.
   113  func (t *T) must(err error) {
   114  	if err != nil {
   115  		t.Fatal(err)
   116  	}
   117  }
   118  
   119  // check gives a test non-fatal error if err is not nil.
   120  func (t *T) check(err error) {
   121  	if err != nil {
   122  		t.Error(err)
   123  	}
   124  }
   125  
   126  // pwd returns the current directory.
   127  func (t *T) pwd() string {
   128  	wd, err := os.Getwd()
   129  	if err != nil {
   130  		t.Fatalf("could not get working directory: %v", err)
   131  	}
   132  	return wd
   133  }
   134  
   135  // cd changes the current directory to the named directory. extra args
   136  // are passed through filepath.Join before cd.
   137  func (t *T) cd(dir string, extra ...string) {
   138  	if t.wd == "" {
   139  		t.wd = t.pwd()
   140  	}
   141  	v := append([]string{dir}, extra...)
   142  	dir = filepath.Join(v...)
   143  	abs, err := filepath.Abs(dir)
   144  	t.must(os.Chdir(dir))
   145  	if err == nil {
   146  		t.setenv("PWD", abs)
   147  	}
   148  }
   149  
   150  // setenv sets an environment variable to use when running the test go
   151  // command.
   152  func (t *T) setenv(name, val string) {
   153  	t.unsetenv(name)
   154  	t.env = append(t.env, name+"="+val)
   155  }
   156  
   157  // unsetenv removes an environment variable.
   158  func (t *T) unsetenv(name string) {
   159  	if t.env == nil {
   160  		t.env = append([]string(nil), os.Environ()...)
   161  	}
   162  	for i, v := range t.env {
   163  		if strings.HasPrefix(v, name+"=") {
   164  			t.env = append(t.env[:i], t.env[i+1:]...)
   165  			break
   166  		}
   167  	}
   168  }
   169  
   170  // doRun runs the test go command, recording stdout and stderr and
   171  // returning exit status.
   172  func (t *T) doRun(args []string) error {
   173  	if !canRun {
   174  		t.Fatal("T.doRun called but canRun false")
   175  	}
   176  	t.Logf("running %v %v", testgb, args)
   177  	cmd := exec.Command(testgb, args...)
   178  	t.stdout.Reset()
   179  	t.stderr.Reset()
   180  	cmd.Stdin = t.stdin
   181  	cmd.Stdout = &t.stdout
   182  	cmd.Stderr = &t.stderr
   183  	cmd.Env = t.env
   184  	status := cmd.Run()
   185  	if t.stdout.Len() > 0 {
   186  		t.Log("standard output:")
   187  		t.Log(t.stdout.String())
   188  	}
   189  	if t.stderr.Len() > 0 {
   190  		t.Log("standard error:")
   191  		t.Log(t.stderr.String())
   192  	}
   193  	t.ran = true
   194  	return status
   195  }
   196  
   197  // run runs the test go command, and expects it to succeed.
   198  func (t *T) run(args ...string) {
   199  	if status := t.doRun(args); status != nil {
   200  		t.Logf("gb %v failed unexpectedly: %v", args, status)
   201  		t.FailNow()
   202  	}
   203  }
   204  
   205  // runFail runs the test go command, and expects it to fail.
   206  func (t *T) runFail(args ...string) {
   207  	if status := t.doRun(args); status == nil {
   208  		t.Fatal(testgb, "succeeded unexpectedly")
   209  	} else {
   210  		t.Log(testgb, "failed as expected:", status)
   211  	}
   212  }
   213  
   214  // getStdout returns standard output of the testgb run as a string.
   215  func (t *T) getStdout() string {
   216  	if !t.ran {
   217  		t.Fatal("internal testsuite error: stdout called before run")
   218  	}
   219  	return t.stdout.String()
   220  }
   221  
   222  // getStderr returns standard error of the testgb run as a string.
   223  func (t *T) getStderr() string {
   224  	if !t.ran {
   225  		t.Fatal("internal testsuite error: stdout called before run")
   226  	}
   227  	return t.stderr.String()
   228  }
   229  
   230  // doGrepMatch looks for a regular expression in a buffer, and returns
   231  // whether it is found.  The regular expression is matched against
   232  // each line separately, as with the grep command.
   233  func (t *T) doGrepMatch(match string, b *bytes.Buffer) bool {
   234  	if !t.ran {
   235  		t.Fatal("internal testsuite error: grep called before run")
   236  	}
   237  	re := regexp.MustCompile(match)
   238  	for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) {
   239  		if re.Match(ln) {
   240  			return true
   241  		}
   242  	}
   243  	return false
   244  }
   245  
   246  // doGrep looks for a regular expression in a buffer and fails if it
   247  // is not found.  The name argument is the name of the output we are
   248  // searching, "output" or "error".  The msg argument is logged on
   249  // failure.
   250  func (t *T) doGrep(match string, b *bytes.Buffer, name, msg string) {
   251  	if !t.doGrepMatch(match, b) {
   252  		t.Log(msg)
   253  		t.Logf("pattern %v not found in standard %s", match, name)
   254  		t.FailNow()
   255  	}
   256  }
   257  
   258  // grepStdout looks for a regular expression in the test run's
   259  // standard output and fails, logging msg, if it is not found.
   260  func (t *T) grepStdout(match, msg string) {
   261  	t.doGrep(match, &t.stdout, "output", msg)
   262  }
   263  
   264  // grepStderr looks for a regular expression in the test run's
   265  // standard error and fails, logging msg, if it is not found.
   266  func (t *T) grepStderr(match, msg string) {
   267  	t.doGrep(match, &t.stderr, "error", msg)
   268  }
   269  
   270  // grepBoth looks for a regular expression in the test run's standard
   271  // output or stand error and fails, logging msg, if it is not found.
   272  func (t *T) grepBoth(match, msg string) {
   273  	if !t.doGrepMatch(match, &t.stdout) && !t.doGrepMatch(match, &t.stderr) {
   274  		t.Log(msg)
   275  		t.Logf("pattern %v not found in standard output or standard error", match)
   276  		t.FailNow()
   277  	}
   278  }
   279  
   280  // doGrepNot looks for a regular expression in a buffer and fails if
   281  // it is found.  The name and msg arguments are as for doGrep.
   282  func (t *T) doGrepNot(match string, b *bytes.Buffer, name, msg string) {
   283  	if t.doGrepMatch(match, b) {
   284  		t.Log(msg)
   285  		t.Logf("pattern %v found unexpectedly in standard %s", match, name)
   286  		t.FailNow()
   287  	}
   288  }
   289  
   290  // grepStdoutNot looks for a regular expression in the test run's
   291  // standard output and fails, logging msg, if it is found.
   292  func (t *T) grepStdoutNot(match, msg string) {
   293  	t.doGrepNot(match, &t.stdout, "output", msg)
   294  }
   295  
   296  // grepStderrNot looks for a regular expression in the test run's
   297  // standard error and fails, logging msg, if it is found.
   298  func (t *T) grepStderrNot(match, msg string) {
   299  	t.doGrepNot(match, &t.stderr, "error", msg)
   300  }
   301  
   302  // grepBothNot looks for a regular expression in the test run's
   303  // standard output or stand error and fails, logging msg, if it is
   304  // found.
   305  func (t *T) grepBothNot(match, msg string) {
   306  	if t.doGrepMatch(match, &t.stdout) || t.doGrepMatch(match, &t.stderr) {
   307  		t.Log(msg)
   308  		t.Fatalf("pattern %v found unexpectedly in standard output or standard error", match)
   309  	}
   310  }
   311  
   312  // doGrepCount counts the number of times a regexp is seen in a buffer.
   313  func (t *T) doGrepCount(match string, b *bytes.Buffer) int {
   314  	if !t.ran {
   315  		t.Fatal("internal testsuite error: doGrepCount called before run")
   316  	}
   317  	re := regexp.MustCompile(match)
   318  	c := 0
   319  	for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) {
   320  		if re.Match(ln) {
   321  			c++
   322  		}
   323  	}
   324  	return c
   325  }
   326  
   327  // grepCountStdout returns the number of times a regexp is seen in
   328  // standard output.
   329  func (t *T) grepCountStdout(match string) int {
   330  	return t.doGrepCount(match, &t.stdout)
   331  }
   332  
   333  // grepCountStderr returns the number of times a regexp is seen in
   334  // standard error.
   335  func (t *T) grepCountStderr(match string) int {
   336  	return t.doGrepCount(match, &t.stderr)
   337  }
   338  
   339  // grepCountBoth returns the number of times a regexp is seen in both
   340  // standard output and standard error.
   341  func (t *T) grepCountBoth(match string) int {
   342  	return t.doGrepCount(match, &t.stdout) + t.doGrepCount(match, &t.stderr)
   343  }
   344  
   345  // creatingTemp records that the test plans to create a temporary file
   346  // or directory.  If the file or directory exists already, it will be
   347  // removed.  When the test completes, the file or directory will be
   348  // removed if it exists.
   349  func (t *T) creatingTemp(path string) {
   350  	if filepath.IsAbs(path) && !strings.HasPrefix(path, t.tempdir) {
   351  		t.Fatal("internal testsuite error: creatingTemp(%q) with absolute path not in temporary directory", path)
   352  	}
   353  	// If we have changed the working directory, make sure we have
   354  	// an absolute path, because we are going to change directory
   355  	// back before we remove the temporary.
   356  	if t.wd != "" && !filepath.IsAbs(path) {
   357  		path = filepath.Join(t.pwd(), path)
   358  	}
   359  	t.must(os.RemoveAll(path))
   360  	t.temps = append(t.temps, path)
   361  }
   362  
   363  // makeTempdir makes a temporary directory for a run of testgb.  If
   364  // the temporary directory was already created, this does nothing.
   365  func (t *T) makeTempdir() {
   366  	if t.tempdir == "" {
   367  		var err error
   368  		t.tempdir, err = ioutil.TempDir("", "testgb")
   369  		t.must(err)
   370  		t.tempdir, err = filepath.EvalSymlinks(t.tempdir) // resolve OSX's stupid symlinked /tmp
   371  		t.must(err)
   372  	}
   373  }
   374  
   375  // tempFile adds a temporary file for a run of testgb.
   376  func (t *T) tempFile(path, contents string) {
   377  	t.makeTempdir()
   378  	t.must(os.MkdirAll(filepath.Join(t.tempdir, filepath.Dir(path)), 0755))
   379  	bytes := []byte(contents)
   380  	if strings.HasSuffix(path, ".go") {
   381  		formatted, err := format.Source(bytes)
   382  		if err == nil {
   383  			bytes = formatted
   384  		}
   385  	}
   386  	t.must(ioutil.WriteFile(filepath.Join(t.tempdir, path), bytes, 0644))
   387  }
   388  
   389  // tempDir adds a temporary directory for a run of testgb.
   390  func (t *T) tempDir(path string) string {
   391  	t.makeTempdir()
   392  	path = filepath.Join(t.tempdir, path)
   393  	if err := os.MkdirAll(path, 0755); err != nil && !os.IsExist(err) {
   394  		t.Fatal(err)
   395  	}
   396  	return path
   397  }
   398  
   399  // symlink adds a symlink from src to dst.
   400  func (t *T) symlink(src, dst string) string {
   401  	t.makeTempdir()
   402  	src = filepath.Join(t.tempdir, src)
   403  	dst = filepath.Join(t.tempdir, dst)
   404  	t.must(os.Symlink(src, dst))
   405  	return dst
   406  }
   407  
   408  // path returns the absolute pathname to file with the temporary
   409  // directory.
   410  func (t *T) path(names ...string) string {
   411  	if t.tempdir == "" {
   412  		t.Fatalf("internal testsuite error: path(%q) with no tempdir", filepath.Join(names...))
   413  	}
   414  	if len(names) == 0 || names[0] == "." {
   415  		return t.tempdir
   416  	}
   417  	return filepath.Join(append([]string{t.tempdir}, names...)...)
   418  }
   419  
   420  // mustExist fails if path does not exists.
   421  func (t *T) mustExist(path string) {
   422  	if _, err := os.Stat(path); err != nil {
   423  		t.Fatalf("%s does not exist (%v)", path, err)
   424  	}
   425  }
   426  
   427  // mustNotExist fails if path exists.
   428  func (t *T) mustNotExist(path string) {
   429  	if _, err := os.Stat(path); err == nil || !os.IsNotExist(err) {
   430  		t.Fatalf("%s exists but should not (%v)", path, err)
   431  	}
   432  }
   433  
   434  // mustBeEmpty fails if root is not a directory or is not empty.
   435  func (t *T) mustBeEmpty(root string) {
   436  	fi, err := os.Stat(root)
   437  	if err != nil {
   438  		t.Fatalf("failed to stat: %s: %v", root, err)
   439  	}
   440  	if !fi.IsDir() {
   441  		t.Fatalf("%s exists but is not a directory", root)
   442  	}
   443  	var found []string
   444  	fn := func(path string, info os.FileInfo, err error) error {
   445  		if path == root {
   446  			return nil
   447  		}
   448  		if err != nil {
   449  			t.Fatalf("error during walk at %s: %v", path, err)
   450  		}
   451  		found = append(found, path)
   452  		return nil
   453  	}
   454  	filepath.Walk(root, fn)
   455  	if len(found) > 0 {
   456  		t.Fatalf("expected %s to be empty, found %s", root, found)
   457  	}
   458  }
   459  
   460  // wantExecutable fails with msg if path is not executable.
   461  func (t *T) wantExecutable(path, msg string) {
   462  	if st, err := os.Stat(path); err != nil {
   463  		if !os.IsNotExist(err) {
   464  			t.Log(err)
   465  		}
   466  		t.Fatal(msg)
   467  	} else {
   468  		if runtime.GOOS != "windows" && st.Mode()&0111 == 0 {
   469  			t.Fatalf("binary %s exists but is not executable", path)
   470  		}
   471  	}
   472  }
   473  
   474  // wantArchive fails if path is not an archive.
   475  func (t *T) wantArchive(path string) {
   476  	f, err := os.Open(path)
   477  	if err != nil {
   478  		t.Fatal(err)
   479  	}
   480  	buf := make([]byte, 100)
   481  	io.ReadFull(f, buf)
   482  	f.Close()
   483  	if !bytes.HasPrefix(buf, []byte("!<arch>\n")) {
   484  		t.Fatalf("file %s exists but is not an archive", path)
   485  	}
   486  }
   487  
   488  // isStale returns whether pkg is stale.
   489  func (t *T) isStale(pkg string) bool {
   490  	t.run("list", "-f", "{{.Stale}}", pkg)
   491  	switch v := strings.TrimSpace(t.getStdout()); v {
   492  	case "true":
   493  		return true
   494  	case "false":
   495  		return false
   496  	default:
   497  		t.Fatalf("unexpected output checking staleness of package %v: %v", pkg, v)
   498  		panic("unreachable")
   499  	}
   500  }
   501  
   502  // wantStale fails with msg if pkg is not stale.
   503  func (t *T) wantStale(pkg, msg string) {
   504  	if !t.isStale(pkg) {
   505  		t.Fatal(msg)
   506  	}
   507  }
   508  
   509  // wantNotStale fails with msg if pkg is stale.
   510  func (t *T) wantNotStale(pkg, msg string) {
   511  	if t.isStale(pkg) {
   512  		t.Fatal(msg)
   513  	}
   514  }
   515  
   516  // cleanup cleans up a test that runs testgb.
   517  func (t *T) cleanup() {
   518  	if t.wd != "" {
   519  		if err := os.Chdir(t.wd); err != nil {
   520  			// We are unlikely to be able to continue.
   521  			fmt.Fprintln(os.Stderr, "could not restore working directory, crashing:", err)
   522  			os.Exit(2)
   523  		}
   524  	}
   525  	for _, path := range t.temps {
   526  		t.check(os.RemoveAll(path))
   527  	}
   528  	if t.tempdir != "" {
   529  		t.check(os.RemoveAll(t.tempdir))
   530  	}
   531  }
   532  
   533  // resetReadOnlyFlagAll resets windows read-only flag
   534  // set on path and any children it contains.
   535  // The flag is set by git and has to be removed.
   536  // os.Remove refuses to remove files with read-only flag set.
   537  func (t *T) resetReadOnlyFlagAll(path string) {
   538  	fi, err := os.Stat(path)
   539  	if err != nil {
   540  		t.Fatalf("resetReadOnlyFlagAll(%q) failed: %v", path, err)
   541  	}
   542  	if !fi.IsDir() {
   543  		err := os.Chmod(path, 0666)
   544  		if err != nil {
   545  			t.Fatalf("resetReadOnlyFlagAll(%q) failed: %v", path, err)
   546  		}
   547  	}
   548  	fd, err := os.Open(path)
   549  	if err != nil {
   550  		t.Fatalf("resetReadOnlyFlagAll(%q) failed: %v", path, err)
   551  	}
   552  	defer fd.Close()
   553  	names, _ := fd.Readdirnames(-1)
   554  	for _, name := range names {
   555  		t.resetReadOnlyFlagAll(path + string(filepath.Separator) + name)
   556  	}
   557  }
   558  
   559  // Invoking plain "gb" should print usage to stderr and exit with 2.
   560  func TestNoArguments(t *testing.T) {
   561  	gb := T{T: t}
   562  	defer gb.cleanup()
   563  
   564  	gb.tempDir("src")
   565  	gb.cd(gb.tempdir)
   566  	gb.runFail()
   567  	gb.grepStderr("^Usage:", `expected "Usage: ..."`)
   568  }
   569  
   570  // Invoking plain "gb" outside a project should print to stderr and exit with 2.
   571  func TestOutsideProject(t *testing.T) {
   572  	gb := T{T: t}
   573  	defer gb.cleanup()
   574  
   575  	gb.tempDir("x")
   576  	gb.cd(gb.tempdir, "x")
   577  	gb.runFail()
   578  	gb.grepStderr("^Usage:", `expected "Usage: ..."`)
   579  }
   580  
   581  // Invoking gb outside a project should print to stderr and exit with 2.
   582  func TestInfoOutsideProject(t *testing.T) {
   583  	gb := T{T: t}
   584  	defer gb.cleanup()
   585  
   586  	gb.tempDir("x")
   587  	gb.cd(gb.tempdir, "x")
   588  	gb.runFail("info")
   589  	regex := `FATAL: unable to construct context: could not locate project root: could not find project root in "` +
   590  		regexp.QuoteMeta(filepath.Join(gb.tempdir, "x")) +
   591  		`" or its parents`
   592  	gb.grepStderr(regex, "expected FATAL")
   593  }
   594  
   595  // Invoking gb outside a project with -R should succeed.
   596  func TestInfoWithMinusR(t *testing.T) {
   597  	gb := T{T: t}
   598  	defer gb.cleanup()
   599  
   600  	gb.tempDir("x")
   601  	gb.tempDir("y")
   602  	gb.tempDir("y/src")
   603  	gb.cd(gb.tempdir, "x")
   604  	gb.run("info", "-R", filepath.Join(gb.tempdir, "y"))
   605  	gb.grepStdout(`^GB_PROJECT_DIR="`+regexp.QuoteMeta(filepath.Join(gb.tempdir, "y"))+`"$`, "missing GB_PROJECT_DIR")
   606  }
   607  
   608  func TestInfoCmd(t *testing.T) {
   609  	gb := T{T: t}
   610  	defer gb.cleanup()
   611  
   612  	gb.tempDir("src")
   613  	gb.cd(gb.tempdir)
   614  	gb.run("info")
   615  	gb.grepStdout(`^GB_PROJECT_DIR="`+regexp.QuoteMeta(gb.tempdir)+`"$`, "missing GB_PROJECT_DIR")
   616  	gb.grepStdout(`^GB_SRC_PATH="`+regexp.QuoteMeta(filepath.Join(gb.tempdir, "src")+string(filepath.ListSeparator)+filepath.Join(gb.tempdir, "vendor", "src"))+`"$`, "missing GB_SRC_PATH")
   617  	gb.grepStdout(`^GB_PKG_DIR="`+regexp.QuoteMeta(filepath.Join(gb.tempdir, "pkg", runtime.GOOS+"-"+runtime.GOARCH))+`"$`, "missing GB_PKG_DIR")
   618  	gb.grepStdout(`^GB_BIN_SUFFIX="-`+runtime.GOOS+"-"+runtime.GOARCH+`"$`, "missing GB_BIN_SUFFIX")
   619  	gb.grepStdout(`^GB_GOROOT="`+regexp.QuoteMeta(runtime.GOROOT())+`"$`, "missing GB_GOROOT")
   620  }
   621  
   622  func TestInfoWithArgs(t *testing.T) {
   623  	gb := T{T: t}
   624  	defer gb.cleanup()
   625  
   626  	gb.tempDir("src")
   627  	gb.cd(gb.tempdir)
   628  	gb.run("info", "GB_PROJECT_DIR", "GB_MISSING", "GB_GOROOT")
   629  	gb.grepStdout(`^`+regexp.QuoteMeta(gb.tempdir), "missing "+regexp.QuoteMeta(gb.tempdir))
   630  	gb.grepStdout(`^`+regexp.QuoteMeta(runtime.GOROOT()), "missing "+regexp.QuoteMeta(runtime.GOROOT()))
   631  	// second line should be empty
   632  	lines := bytes.Split(gb.stdout.Bytes(), []byte{'\n'})
   633  	if len(lines[1]) != 0 {
   634  		t.Fatal("want 0, got", len(lines[1]))
   635  	}
   636  }
   637  
   638  // Only succeeds if source order is preserved.
   639  func TestSourceFileNameOrderPreserved(t *testing.T) {
   640  	gb := T{T: t}
   641  	defer gb.cleanup()
   642  	gb.tempDir("src")
   643  	gb.tempDir("src/testorder")
   644  	gb.tempFile("src/testorder/example1_test.go", `// Copyright 2013 The Go Authors.  All rights reserved.
   645  // Use of this source code is governed by a BSD-style
   646  // license that can be found in the LICENSE file.
   647  
   648  // Make sure that go test runs Example_Z before Example_A, preserving source order.
   649  
   650  package p
   651  
   652  import "fmt"
   653  
   654  var n int
   655  
   656  func Example_Z() {
   657  	n++
   658  	fmt.Println(n)
   659  	// Output: 1
   660  }
   661  
   662  func Example_A() {
   663  	n++
   664  	fmt.Println(n)
   665  	// Output: 2
   666  }
   667  `)
   668  	gb.tempFile("src/testorder/example2_test.go", `// Copyright 2013 The Go Authors.  All rights reserved.
   669  // Use of this source code is governed by a BSD-style
   670  // license that can be found in the LICENSE file.
   671  
   672  // Make sure that go test runs Example_Y before Example_B, preserving source order.
   673  
   674  package p
   675  
   676  import "fmt"
   677  
   678  func Example_Y() {
   679  	n++
   680  	fmt.Println(n)
   681  	// Output: 3
   682  }
   683  
   684  func Example_B() {
   685  	n++
   686  	fmt.Println(n)
   687  	// Output: 4
   688  }
   689  `)
   690  	gb.cd(gb.tempdir)
   691  	gb.run("test", "testorder")
   692  }
   693  
   694  func TestBuildPackage(t *testing.T) {
   695  	gb := T{T: t}
   696  	defer gb.cleanup()
   697  	gb.tempDir("src")
   698  	gb.tempDir("src/pkg1")
   699  	gb.tempFile("src/pkg1/pkg.go", `package pkg1
   700  import "fmt"
   701  
   702  func helloworld() {
   703  	fmt.Println("hello world!")
   704  }
   705  `)
   706  	gb.cd(gb.tempdir)
   707  	tmpdir := gb.tempDir("tmp")
   708  	gb.setenv("TMP", tmpdir)
   709  	gb.run("build")
   710  	gb.grepStdout("^pkg1$", `expected "pkg1"`)
   711  	gb.mustBeEmpty(tmpdir)
   712  	gb.wantArchive(filepath.Join(gb.tempdir, "pkg", runtime.GOOS+"-"+runtime.GOARCH, "pkg1.a"))
   713  }
   714  
   715  func TestBuildOnlyOnePackage(t *testing.T) {
   716  	gb := T{T: t}
   717  	defer gb.cleanup()
   718  	gb.tempDir("src")
   719  	gb.tempDir("src/pkg1")
   720  	gb.tempFile("src/pkg1/pkg.go", `package pkg1
   721  import "fmt"
   722  
   723  func helloworld() {
   724  	fmt.Println("hello world!")
   725  }
   726  `)
   727  	gb.tempDir("src/pkg2")
   728  	gb.tempFile("src/pkg2/pkg.go", `package pkg2
   729  import "fmt"
   730  
   731  func helloworld() {
   732  	fmt.Println("hello world!")
   733  }
   734  `)
   735  	gb.cd(gb.tempdir)
   736  	tmpdir := gb.tempDir("tmp")
   737  	gb.setenv("TMP", tmpdir)
   738  	gb.run("build", "pkg1")
   739  	gb.grepStdout("^pkg1$", `expected "pkg1"`)
   740  	gb.grepStdoutNot("^pkg2$", `did not expect "pkg2"`)
   741  	gb.mustBeEmpty(tmpdir)
   742  	gb.wantArchive(filepath.Join(gb.tempdir, "pkg", runtime.GOOS+"-"+runtime.GOARCH, "pkg1.a"))
   743  }
   744  
   745  func TestBuildOnlyOnePackageFromWorkingDir(t *testing.T) {
   746  	gb := T{T: t}
   747  	defer gb.cleanup()
   748  	gb.tempDir("src")
   749  	gb.tempDir("src/pkg1")
   750  	gb.tempFile("src/pkg1/pkg.go", `package pkg1
   751  import "fmt"
   752  
   753  func helloworld() {
   754  	fmt.Println("hello world!")
   755  }
   756  `)
   757  	gb.tempDir("src/pkg2")
   758  	gb.tempFile("src/pkg2/pkg.go", `package pkg2
   759  import "fmt"
   760  
   761  func helloworld() {
   762  	fmt.Println("hello world!")
   763  }
   764  `)
   765  	gb.cd(filepath.Join(gb.tempdir, "src", "pkg1"))
   766  	tmpdir := gb.tempDir("tmp")
   767  	gb.setenv("TMP", tmpdir)
   768  	gb.run("build")
   769  	gb.grepStdout("^pkg1$", `expected "pkg1"`)
   770  	gb.grepStdoutNot("^pkg2$", `did not expect "pkg2"`)
   771  	gb.mustBeEmpty(tmpdir)
   772  	gb.wantArchive(filepath.Join(gb.tempdir, "pkg", runtime.GOOS+"-"+runtime.GOARCH, "pkg1.a"))
   773  }
   774  
   775  func TestBuildPackageWrongPackage(t *testing.T) {
   776  	gb := T{T: t}
   777  	defer gb.cleanup()
   778  	gb.tempDir("src")
   779  	gb.tempDir("src/pkg1")
   780  	gb.tempFile("src/pkg1/pkg.go", `package pkg1
   781  import "fmt"
   782  
   783  func helloworld() {
   784  	fmt.Println("hello world!")
   785  }
   786  `)
   787  	gb.cd(gb.tempdir)
   788  	gb.runFail("build", "pkg2")
   789  	gb.grepStderr(`^FATAL: command "build" failed: failed to resolve import path "pkg2": import "pkg2": not found`, "expected FATAL")
   790  }
   791  
   792  func TestBuildPackageNoSource(t *testing.T) {
   793  	gb := T{T: t}
   794  	defer gb.cleanup()
   795  	gb.tempDir("src")
   796  	gb.tempDir("src/pkg1")
   797  	gb.cd(gb.tempdir)
   798  	gb.runFail("build", "pkg1")
   799  	gb.grepStderr(`^FATAL: command "build" failed: no packages supplied`, "expected FATAL")
   800  }
   801  
   802  func TestTestPackageNoTests(t *testing.T) {
   803  	gb := T{T: t}
   804  	defer gb.cleanup()
   805  	gb.tempDir("src")
   806  	gb.tempDir("src/pkg1")
   807  	gb.tempFile("src/pkg1/pkg.go", `package pkg1
   808  import "fmt"
   809  
   810  func helloworld() {
   811  	fmt.Println("hello world!")
   812  }
   813  `)
   814  	gb.cd(gb.tempdir)
   815  	tmpdir := gb.tempDir("tmp")
   816  	gb.setenv("TMP", tmpdir)
   817  	gb.run("test", "pkg1")
   818  	gb.grepStdout("^pkg1$", `expected "pkg1"`)
   819  	gb.mustBeEmpty(tmpdir)
   820  	gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created
   821  }
   822  
   823  // test that compiling A in test scope compiles B in regular scope
   824  func TestTestDependantPackage(t *testing.T) {
   825  	gb := T{T: t}
   826  	defer gb.cleanup()
   827  	gb.tempDir("src")
   828  	gb.tempDir("src/A")
   829  	gb.tempDir("src/B")
   830  	gb.tempFile("src/B/B.go", `package B
   831  const X = 1
   832  `)
   833  	gb.tempFile("src/A/A_test.go", `package A
   834  import "testing"
   835  import "B"
   836  
   837  func TestX(t *testing.T) {
   838  	if B.X != 1 {
   839  		t.Fatal("expected 1, got %d", B.X)
   840  	}
   841  }
   842  `)
   843  	gb.cd(gb.tempdir)
   844  	tmpdir := gb.tempDir("tmp")
   845  	gb.setenv("TMP", tmpdir)
   846  	gb.run("test", "A")
   847  	gb.grepStdout("^B$", `expected "B"`) // output from build action
   848  	gb.grepStdout("^A$", `expected "A"`) // output from test action
   849  	gb.mustBeEmpty(tmpdir)
   850  	gb.wantArchive(filepath.Join(gb.tempdir, "pkg", runtime.GOOS+"-"+runtime.GOARCH, "B.a"))
   851  }
   852  
   853  func TestTestPackageOnlyTests(t *testing.T) {
   854  	gb := T{T: t}
   855  	defer gb.cleanup()
   856  	gb.tempDir("src")
   857  	gb.tempDir("src/pkg1")
   858  	gb.tempFile("src/pkg1/pkg_test.go", `package pkg1
   859  import "testing"
   860  
   861  func TestTest(t *testing.T) {
   862  	t.Log("hello")
   863  }
   864  `)
   865  	gb.cd(gb.tempdir)
   866  	tmpdir := gb.tempDir("tmp")
   867  	gb.setenv("TMP", tmpdir)
   868  	gb.run("test", "pkg1")
   869  	gb.grepStdout("^pkg1$", `expected "pkg1"`)
   870  	gb.mustBeEmpty(tmpdir)
   871  	gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created
   872  }
   873  
   874  func TestTestPackageNopeMode(t *testing.T) {
   875  	gb := T{T: t}
   876  	defer gb.cleanup()
   877  	gb.tempDir("src")
   878  	gb.tempDir("src/pkg1")
   879  	gb.tempFile("src/pkg1/pkg_test.go", `package pkg1
   880  import "testing"
   881  
   882  func TestTest(t *testing.T) {
   883  	t.Log("hello")
   884  }
   885  `)
   886  	gb.cd(gb.tempdir)
   887  	tmpdir := gb.tempDir("tmp")
   888  	gb.setenv("TMP", tmpdir)
   889  	gb.run("test", "-n", "pkg1")
   890  	gb.grepStdout("^pkg1$", `expected "pkg1"`)
   891  	gb.mustBeEmpty(tmpdir)
   892  	gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created
   893  }
   894  
   895  func TestTestPackageFailedToBuild(t *testing.T) {
   896  	gb := T{T: t}
   897  	defer gb.cleanup()
   898  	gb.tempDir("src")
   899  	gb.tempDir("src/pkg1")
   900  	gb.tempFile("src/pkg1/pkg_test.go", `package pkg1
   901  import "testing"
   902  
   903  func TestTest(t *testing.T) {
   904  	t.Log("hello"	// missing parens
   905  }
   906  `)
   907  	gb.cd(gb.tempdir)
   908  	tmpdir := gb.tempDir("tmp")
   909  	gb.setenv("TMP", tmpdir)
   910  	gb.runFail("test")
   911  	gb.grepStderr(`FATAL: command "test" failed:`, "expected FATAL")
   912  	gb.mustBeEmpty(tmpdir)
   913  	gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created
   914  }
   915  
   916  func TestTestPackageTestFailed(t *testing.T) {
   917  	gb := T{T: t}
   918  	defer gb.cleanup()
   919  	gb.tempDir("src")
   920  	gb.tempDir("src/pkg1")
   921  	gb.tempFile("src/pkg1/pkg_test.go", `package pkg1
   922  import "testing"
   923  
   924  func TestTest(t *testing.T) {
   925  	t.Error("failed")
   926  }
   927  `)
   928  	gb.cd(gb.tempdir)
   929  	tmpdir := gb.tempDir("tmp")
   930  	gb.setenv("TMP", tmpdir)
   931  	gb.runFail("test")
   932  	gb.grepStderr("^# pkg1$", "expected # pkg1")
   933  	gb.grepStdout("pkg_test.go:6: failed", "expected message from test")
   934  	gb.mustBeEmpty(tmpdir)
   935  	gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created
   936  }
   937  
   938  func TestTestPackageMinusV(t *testing.T) {
   939  	gb := T{T: t}
   940  	defer gb.cleanup()
   941  	gb.tempDir("src")
   942  	gb.tempDir("src/pkg1")
   943  	gb.tempFile("src/pkg1/pkg_test.go", `package pkg1
   944  import "testing"
   945  
   946  func TestTest(t *testing.T) {
   947  	t.Logf("hello")
   948  }
   949  `)
   950  	gb.cd(gb.tempdir)
   951  	tmpdir := gb.tempDir("tmp")
   952  	gb.setenv("TMP", tmpdir)
   953  	gb.run("test", "-v")
   954  	gb.grepStdout("^pkg1$", "expected pkg1")
   955  	gb.grepStdout("pkg_test.go:6: hello", "expected output from test binary")
   956  	gb.grepStdout("PASS", "expected PASS")
   957  	gb.mustBeEmpty(tmpdir)
   958  	gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created
   959  }
   960  
   961  const issue349 = `package main
   962  
   963  import (
   964      "flag"
   965      "testing"
   966  )
   967  
   968  var name = flag.String("name", "nsf", "what is your name")
   969  
   970  func TestX(t *testing.T) {
   971      if *name != "jardin" {
   972          t.Fatalf("got: '%s', expected: 'jardin'", *name)
   973      }
   974  }
   975  `
   976  
   977  // https://github.com/constabulary/gb/issues/349
   978  func TestTestGbTestPassesUnknownFlags(t *testing.T) {
   979  	gb := T{T: t}
   980  	defer gb.cleanup()
   981  	gb.tempDir("src")
   982  	gb.tempDir("src/projectx")
   983  	gb.tempFile("src/projectx/main_test.go", issue349)
   984  	gb.cd(gb.tempdir)
   985  	tmpdir := gb.tempDir("tmp")
   986  	gb.setenv("TMP", tmpdir)
   987  	gb.run("test", "-name=jardin")
   988  	gb.grepStdout("^projectx$", "expected projectx") // output from gb test
   989  	gb.mustBeEmpty(tmpdir)
   990  	gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created
   991  }
   992  
   993  const issue473 = `package main
   994  
   995  import (
   996      "flag"
   997      "testing"
   998  )
   999  
  1000  var name = flag.String("name", "nsf", "what is your name")
  1001  
  1002  func TestX(t *testing.T) {
  1003  }
  1004  
  1005  func TestY(t *testing.T) {
  1006  }
  1007  `
  1008  
  1009  // https://github.com/constabulary/gb/issues/473
  1010  func TestGbTestIssue473a(t *testing.T) {
  1011  	gb := T{T: t}
  1012  	defer gb.cleanup()
  1013  	gb.tempDir("src")
  1014  	gb.tempDir("src/projectx")
  1015  	gb.tempFile("src/projectx/main_test.go", issue473)
  1016  	gb.cd(gb.tempdir)
  1017  	tmpdir := gb.tempDir("tmp")
  1018  	gb.setenv("TMP", tmpdir)
  1019  	gb.run("test", "-v", "projectx", "-run", "TestX")
  1020  	gb.grepStdout("^projectx$", "expected projectx") // output from gb test
  1021  	gb.grepStdout("TestX", "expected TestX")
  1022  	gb.grepStdoutNot("TestY", "expected TestY")
  1023  	gb.mustBeEmpty(tmpdir)
  1024  	gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created
  1025  }
  1026  
  1027  func TestGbTestIssue473b(t *testing.T) {
  1028  	gb := T{T: t}
  1029  	defer gb.cleanup()
  1030  	gb.tempDir("src")
  1031  	gb.tempDir("src/projectx")
  1032  	gb.tempFile("src/projectx/main_test.go", issue473)
  1033  	gb.cd(gb.tempdir)
  1034  	tmpdir := gb.tempDir("tmp")
  1035  	gb.setenv("TMP", tmpdir)
  1036  	gb.run("test", "-v", "-run", "TestX", "projectx")
  1037  	gb.grepStdout("^projectx$", "expected projectx") // output from gb test
  1038  	gb.grepStdout("TestX", "expected TestX")
  1039  	gb.grepStdoutNot("TestY", "expected TestY")
  1040  	gb.mustBeEmpty(tmpdir)
  1041  	gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created
  1042  }
  1043  
  1044  func TestGbTestIssue473c(t *testing.T) {
  1045  	gb := T{T: t}
  1046  	defer gb.cleanup()
  1047  	gb.tempDir("src")
  1048  	gb.tempDir("src/projectx")
  1049  	gb.tempFile("src/projectx/main_test.go", issue473)
  1050  	gb.cd(gb.tempdir)
  1051  	tmpdir := gb.tempDir("tmp")
  1052  	gb.setenv("TMP", tmpdir)
  1053  	gb.run("test", "-v", "projectx")
  1054  	gb.grepStdout("^projectx$", "expected projectx") // output from gb test
  1055  	gb.grepStdout("TestX", "expected TestX")
  1056  	gb.grepStdout("TestY", "expected TestY")
  1057  	gb.mustBeEmpty(tmpdir)
  1058  	gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created
  1059  }
  1060  
  1061  func TestGbTestIssue473d(t *testing.T) {
  1062  	gb := T{T: t}
  1063  	defer gb.cleanup()
  1064  	gb.tempDir("src")
  1065  	gb.tempDir("src/projectx")
  1066  	gb.tempFile("src/projectx/main_test.go", issue473)
  1067  	gb.cd(gb.tempdir)
  1068  	tmpdir := gb.tempDir("tmp")
  1069  	gb.setenv("TMP", tmpdir)
  1070  	gb.run("test", "projectx", "-v")
  1071  	gb.grepStdout("^projectx$", "expected projectx") // output from gb test
  1072  	gb.grepStdout("TestX", "expected TestX")
  1073  	gb.grepStdout("TestY", "expected TestY")
  1074  	gb.mustBeEmpty(tmpdir)
  1075  	gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created
  1076  }
  1077  
  1078  // gb list with an empty project succeeds and returns nothing.
  1079  func TestGbListEmpty(t *testing.T) {
  1080  	gb := T{T: t}
  1081  	defer gb.cleanup()
  1082  	gb.tempDir("src")
  1083  	gb.cd(gb.tempdir)
  1084  	tmpdir := gb.tempDir("tmp")
  1085  	gb.setenv("TMP", tmpdir)
  1086  	gb.run("list")
  1087  	gb.grepStdoutNot(".", "expected no output")
  1088  	gb.grepStderrNot(".", "expected no output")
  1089  	gb.mustBeEmpty(tmpdir)
  1090  }
  1091  
  1092  // gb list with a project with source at the top level should return nothing.
  1093  func TestGbListSrcTopLevel(t *testing.T) {
  1094  	gb := T{T: t}
  1095  	defer gb.cleanup()
  1096  	gb.tempDir("src")
  1097  	gb.tempFile("src/main.go", "package main; func main() { println() }")
  1098  	gb.cd(gb.tempdir)
  1099  	gb.run("list")
  1100  	gb.grepStdoutNot(".", "expected no output")
  1101  	gb.grepStderrNot(".", "expected no output")
  1102  }
  1103  
  1104  func TestGbListSrcCmd(t *testing.T) {
  1105  	gb := T{T: t}
  1106  	defer gb.cleanup()
  1107  	gb.tempDir("src")
  1108  	gb.tempDir("src/cmd")
  1109  	gb.tempFile("src/cmd/main.go", "package main; func main() { println() }")
  1110  	gb.cd(gb.tempdir)
  1111  	gb.run("list")
  1112  	gb.grepStdout("cmd", "expected cmd")
  1113  }
  1114  
  1115  func mklistfixture(gb *T) {
  1116  	gb.tempDir("src/p")
  1117  	gb.tempDir("src/q")
  1118  	gb.tempDir("src/r/s")
  1119  	gb.tempFile("src/p/p.go", "package p; const P = 'p'")
  1120  	gb.tempFile("src/q/q.go", "package p; const Q = 'q'") // package name differs from import path
  1121  	gb.tempFile("src/r/r.go", "package r; const R = 'r'")
  1122  	gb.tempFile("src/r/s/s.go", "package s; const S = 's'")
  1123  }
  1124  
  1125  // gb list with a few projects should show them all.
  1126  func TestGbList(t *testing.T) {
  1127  	gb := T{T: t}
  1128  	defer gb.cleanup()
  1129  	mklistfixture(&gb)
  1130  	gb.cd(gb.tempdir)
  1131  	gb.run("list")
  1132  	gb.grepStdout("^p$", "expected 'p'")
  1133  	gb.grepStdout("^q$", "expected 'q'")
  1134  	gb.grepStdout("^r$", "expected 'r'")
  1135  	gb.grepStdout("^r/s$", "expected 'r/s'")
  1136  }
  1137  
  1138  func TestGbListPart(t *testing.T) {
  1139  	gb := T{T: t}
  1140  	defer gb.cleanup()
  1141  	mklistfixture(&gb)
  1142  	gb.cd(gb.tempdir)
  1143  	gb.run("list", "r/...", "q")
  1144  	gb.grepStdoutNot("^p$", "unexpected 'p'")
  1145  	gb.grepStdout("^q$", "expected 'q'")
  1146  	gb.grepStdout("^r$", "expected 'r'")
  1147  	gb.grepStdout("^r/s$", "expected 'r/s'")
  1148  }
  1149  
  1150  func TestGbListPackageNames(t *testing.T) {
  1151  	gb := T{T: t}
  1152  	defer gb.cleanup()
  1153  	mklistfixture(&gb)
  1154  	gb.cd(gb.tempdir)
  1155  	gb.run("list", "-f", "{{ .Name }}")
  1156  	gb.grepStdout("^p$", "expected 'p'")
  1157  	gb.grepStdoutNot("^q$", "unexpected 'q'")
  1158  	gb.grepStdout("^r$", "expected 'r'")
  1159  	gb.grepStdout("^s$", "expected 's'")
  1160  }
  1161  
  1162  func TestGbListFormatFromStdin(t *testing.T) {
  1163  	gb := T{T: t}
  1164  	defer gb.cleanup()
  1165  	mklistfixture(&gb)
  1166  	gb.cd(gb.tempdir)
  1167  	gb.stdin = strings.NewReader("{{ .Name }}")
  1168  	gb.run("list", "-s")
  1169  	gb.grepStdout("^p$", "expected 'p'")
  1170  	gb.grepStdoutNot("^q$", "unexpected 'q'")
  1171  	gb.grepStdout("^r$", "expected 'r'")
  1172  	gb.grepStdout("^s$", "expected 's'")
  1173  }
  1174  
  1175  // TODO(dfc) add tests for -json
  1176  
  1177  func skipWindows(t *testing.T, msg string) {
  1178  	if runtime.GOOS == "windows" {
  1179  		t.Skip("test skipped on windows:", msg)
  1180  	}
  1181  }
  1182  
  1183  // issue 481: check that project detection works correctly
  1184  // in the presence of symlinks above the project root.
  1185  func TestProjectRootDetectionWorksWithParentSymlink(t *testing.T) {
  1186  	skipWindows(t, "no symlinks, lol")
  1187  	gb := T{T: t}
  1188  	defer gb.cleanup()
  1189  
  1190  	gb.tempDir("code/project")
  1191  	gb.tempDir("code/project/src/a")
  1192  	gb.tempFile("code/project/src/a/a.go", "package a; const A = 'a'")
  1193  	root := gb.symlink("code", "code1")
  1194  	gb.cd(filepath.Join(root, "project"))
  1195  	gb.run("list")
  1196  	gb.grepStdout("^a$", "expected 'a'")
  1197  }
  1198  
  1199  func TestProjectRootDetectionWorksWithDirectSymlink(t *testing.T) {
  1200  	skipWindows(t, "no symlinks, lol")
  1201  	gb := T{T: t}
  1202  	defer gb.cleanup()
  1203  
  1204  	gb.tempDir("code/project")
  1205  	gb.tempDir("code/project/src/a")
  1206  	gb.tempFile("code/project/src/a/a.go", "package a; const A = 'a'")
  1207  	root := gb.symlink("code/project", "code/symlink")
  1208  	gb.cd(root)
  1209  	gb.run("list")
  1210  	gb.grepStdout("^a$", "expected 'a'")
  1211  }
  1212  
  1213  // issue 157
  1214  func TestTestWorksWithProjectSymlink(t *testing.T) {
  1215  	skipWindows(t, "no symlinks, lol")
  1216  	gb := T{T: t}
  1217  	defer gb.cleanup()
  1218  
  1219  	gb.tempDir("code/project")
  1220  	gb.tempDir("code/project/src/a")
  1221  	gb.tempFile("code/project/src/a/a.go", "package a; const A = 'a'")
  1222  	gb.tempFile("code/project/src/a/a_test.go", `package a
  1223  
  1224  import "testing"
  1225  
  1226  func TestA(t *testing.T) {
  1227  	if A != 'a' {
  1228  		t.Fatal("expected a, got", A)
  1229  	}
  1230  }
  1231  `)
  1232  	root := gb.symlink("code/project", "code/symlink")
  1233  	gb.cd(root)
  1234  	gb.run("test")
  1235  	gb.grepStdout("^a$", "expected 'a'")
  1236  }
  1237  
  1238  func TestTestWorksInsideProjectSymlink(t *testing.T) {
  1239  	skipWindows(t, "no symlinks, lol")
  1240  	gb := T{T: t}
  1241  	defer gb.cleanup()
  1242  
  1243  	gb.tempDir("code/project")
  1244  	gb.tempDir("code/project/src/a")
  1245  	gb.tempFile("code/project/src/a/a.go", "package a; const A = 'a'")
  1246  	gb.tempFile("code/project/src/a/a_test.go", `package a
  1247  
  1248  import "testing"
  1249  
  1250  func TestA(t *testing.T) {
  1251  	if A != 'a' {
  1252  		t.Fatal("expected a, got", A)
  1253  	}
  1254  }
  1255  `)
  1256  	root := gb.symlink("code/project", "code/symlink")
  1257  	gb.cd(filepath.Join(root, "src", "a"))
  1258  	gb.run("test")
  1259  	gb.grepStdout("^a$", "expected 'a'")
  1260  }
  1261  
  1262  // test -race flag is wired up correctly
  1263  func TestBuildRaceFlag(t *testing.T) {
  1264  	if !canRace {
  1265  		t.Skip("skipping because race detector not supported")
  1266  	}
  1267  
  1268  	gb := T{T: t}
  1269  	defer gb.cleanup()
  1270  
  1271  	gb.tempDir("src/x")
  1272  	gb.tempFile("src/x/x_race.go", "package x\nconst A = 1\n")
  1273  	gb.tempFile("src/x/y.go", "// +build race\n\npackage x\nconst B = 2\n")
  1274  	gb.tempFile("src/x/z.go", "package x\n const C = A +B\n")
  1275  	gb.cd(gb.tempdir)
  1276  	tmpdir := gb.tempDir("tmp")
  1277  	gb.setenv("TMP", tmpdir)
  1278  	gb.run("build", "-race", "x")
  1279  	gb.mustBeEmpty(tmpdir)
  1280  	gb.wantArchive(filepath.Join(gb.tempdir, "pkg", runtime.GOOS+"-"+runtime.GOARCH+"-race", "x.a"))
  1281  }
  1282  
  1283  func TestTestRaceFlag(t *testing.T) {
  1284  	if !canRace {
  1285  		t.Skip("skipping because race detector not supported")
  1286  	}
  1287  
  1288  	gb := T{T: t}
  1289  	defer gb.cleanup()
  1290  
  1291  	gb.tempDir("src/x")
  1292  	gb.tempFile("src/x/x_race.go", "package x\nconst A = 1\n")
  1293  	gb.tempFile("src/x/y.go", "// +build race\n\npackage x\nconst B = 2\n")
  1294  	gb.tempFile("src/x/q.go", "// +build !race\n\npackage x\nconst B = 7\n")
  1295  	gb.tempFile("src/x/x_test.go", `package x
  1296  import "testing"
  1297  
  1298  func TestRaceFlag(t *testing.T) {
  1299  	if A != 1 || B != 2 {
  1300  		t.Fatal("expected", 1, 2,"got", A, B)
  1301  	}
  1302  }
  1303  `)
  1304  	gb.cd(gb.tempdir)
  1305  	tmpdir := gb.tempDir("tmp")
  1306  	gb.setenv("TMP", tmpdir)
  1307  	gb.run("test", "-race", "x")
  1308  	gb.grepStdout("^x$", "expected x") // output from gb test
  1309  	gb.mustBeEmpty(tmpdir)
  1310  	gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created
  1311  }
  1312  
  1313  // check that go test -race builds and runs a racy binary, and that it finds the race.
  1314  func TestTestRace(t *testing.T) {
  1315  	if !canRace {
  1316  		t.Skip("skipping because race detector not supported")
  1317  	}
  1318  	if strings.HasPrefix(runtime.Version(), "go1.4") {
  1319  		t.Skipf("skipping race test as Go version %v incorrectly marks race failures as success", runtime.Version())
  1320  	}
  1321  
  1322  	gb := T{T: t}
  1323  	defer gb.cleanup()
  1324  
  1325  	gb.tempDir("src/race")
  1326  	gb.tempFile("src/race/map_test.go", `package race
  1327  import "testing"
  1328  
  1329  func TestRaceMapRW(t *testing.T) {
  1330          m := make(map[int]int)
  1331          ch := make(chan bool, 1)
  1332          go func() {
  1333                  _ = m[1]
  1334                  ch <- true
  1335          }()
  1336          m[1] = 1
  1337          <-ch
  1338  }
  1339  `)
  1340  	gb.cd(gb.tempdir)
  1341  	tmpdir := gb.tempDir("tmp")
  1342  	gb.setenv("TMP", tmpdir)
  1343  	gb.runFail("test", "-race")
  1344  	gb.mustBeEmpty(tmpdir)
  1345  }
  1346  
  1347  // check that missing -race support generates error message.
  1348  func TestRaceMissing(t *testing.T) {
  1349  	if canRace {
  1350  		t.Skip("skipping because race detector is available")
  1351  	}
  1352  
  1353  	gb := T{T: t}
  1354  	defer gb.cleanup()
  1355  
  1356  	gb.tempDir("src/race")
  1357  	gb.tempFile("src/race/map_test.go", `package race
  1358  import "testing"
  1359  
  1360  func TestRaceMapRW(t *testing.T) {
  1361          m := make(map[int]int)
  1362          ch := make(chan bool, 1)
  1363          go func() {
  1364                  _ = m[1]
  1365                  ch <- true
  1366          }()
  1367          m[1] = 1
  1368          <-ch
  1369  }
  1370  `)
  1371  	gb.cd(gb.tempdir)
  1372  	tmpdir := gb.tempDir("tmp")
  1373  	gb.setenv("TMP", tmpdir)
  1374  	gb.runFail("test", "-race")
  1375  	raceError1 := fmt.Sprintf("FATAL: go installation at %s is missing race support", runtime.GOROOT())
  1376  	raceError2 := fmt.Sprintf("FATAL: race detector not supported on %s/%s", runtime.GOOS, runtime.GOARCH)
  1377  	gb.grepStderr(regexp.QuoteMeta(raceError1)+"|"+regexp.QuoteMeta(raceError2), "expected missing race support message")
  1378  	gb.mustBeEmpty(tmpdir)
  1379  }
  1380  
  1381  // test that gb will no build the stdlib directly, only as transitive deps.
  1382  func TestNoBuildStdlib(t *testing.T) {
  1383  	t.Skip("constabulary/gb#505")
  1384  	gb := T{T: t}
  1385  	defer gb.cleanup()
  1386  	gb.tempDir("src/")
  1387  	gb.cd(gb.tempdir)
  1388  	defer gb.cleanup()
  1389  	gb.runFail("build", "-f", "-F", "net/http")
  1390  }
  1391  
  1392  func TestCrossCompile(t *testing.T) {
  1393  	if strings.HasPrefix(runtime.Version(), "go1.4") {
  1394  		t.Skip("skipping cross compile test, not supported on", runtime.Version())
  1395  	}
  1396  	gb := T{T: t}
  1397  	defer gb.cleanup()
  1398  	gb.tempDir("src/p")
  1399  	gb.tempFile("src/p/main.go", `package main
  1400  func main() { println("hello world") }
  1401  `)
  1402  	gb.cd(gb.tempdir)
  1403  	tmpdir := gb.tempDir("tmp")
  1404  	goos := "windows"
  1405  	if runtime.GOOS == goos {
  1406  		goos = "linux"
  1407  	}
  1408  	goarch := "386"
  1409  	if runtime.GOARCH == goarch {
  1410  		goarch = "amd64"
  1411  	}
  1412  	gb.setenv("TMP", tmpdir)
  1413  	gb.setenv("GOOS", goos)
  1414  	gb.setenv("GOARCH", goarch)
  1415  	gb.run("build")
  1416  	gb.mustBeEmpty(tmpdir)
  1417  	name := fmt.Sprintf("p-%s-%s", goos, goarch)
  1418  	if goos == "windows" {
  1419  		name += ".exe"
  1420  	}
  1421  	gb.mustExist(gb.path("bin", name))
  1422  	gb.wantExecutable(gb.path("bin", name), "expected $PROJECT/bin/p-$GOOS-$GOARCH")
  1423  }
  1424  
  1425  // https://github.com/constabulary/gb/issues/416
  1426  func TestGbBuildBuildsPackgeCalledCmd(t *testing.T) {
  1427  	gb := T{T: t}
  1428  	defer gb.cleanup()
  1429  	gb.tempDir("src/cmd")
  1430  	gb.tempFile("src/cmd/main.go", `package main
  1431  func main() { println("hello world") }
  1432  `)
  1433  	gb.cd(gb.tempdir)
  1434  	tmpdir := gb.tempDir("tmp")
  1435  	gb.setenv("TMP", tmpdir)
  1436  	gb.run("build")
  1437  	gb.mustBeEmpty(tmpdir)
  1438  	gb.grepStdout("^cmd$", "expected cmd")
  1439  	name := "cmd"
  1440  	if runtime.GOOS == "windows" {
  1441  		name += ".exe"
  1442  	}
  1443  	gb.mustExist(gb.path("bin", name))
  1444  	gb.wantExecutable(gb.path("bin", name), "expected $PROJECT/bin/"+name)
  1445  }
  1446  
  1447  // https://github.com/constabulary/gb/issues/492
  1448  func TestGbBuildSubPackageOfCmd(t *testing.T) {
  1449  	gb := T{T: t}
  1450  	defer gb.cleanup()
  1451  	gb.tempDir("src/cmd/hello")
  1452  	gb.tempFile("src/cmd/hello/main.go", `package main
  1453  func main() { println("hello world") }
  1454  `)
  1455  	gb.cd(gb.tempdir)
  1456  	tmpdir := gb.tempDir("tmp")
  1457  	gb.setenv("TMP", tmpdir)
  1458  	gb.run("build")
  1459  	gb.mustBeEmpty(tmpdir)
  1460  	name := "hello"
  1461  	if runtime.GOOS == "windows" {
  1462  		name += ".exe"
  1463  	}
  1464  	gb.wantExecutable(gb.path("bin", name), "expected $PROJECT/bin/hello")
  1465  }
  1466  
  1467  // https://github.com/constabulary/gb/issues/515
  1468  func TestIssue515(t *testing.T) {
  1469  	gb := T{T: t}
  1470  	defer gb.cleanup()
  1471  	gb.tempDir("src/main")
  1472  	gb.tempFile("src/main/main.go", `package main
  1473  
  1474  import (
  1475      "log"
  1476      "net/http"
  1477  )
  1478  
  1479  func main() {
  1480      err := http.ListenAndServe(":8080", nil)
  1481      if err != nil {
  1482          log.Fatal("ListenAndServe: ", err)
  1483      } else {
  1484          log.Print("Server started!")
  1485      }
  1486  }
  1487  `)
  1488  	gb.cd(gb.tempdir)
  1489  	tmpdir := gb.tempDir("tmp")
  1490  	gb.setenv("TMP", tmpdir)
  1491  	gb.run("build")
  1492  	gb.mustBeEmpty(tmpdir)
  1493  	name := "main"
  1494  	if runtime.GOOS == "windows" {
  1495  		name += ".exe"
  1496  	}
  1497  	gb.wantExecutable(gb.path("bin", name), "expected $PROJECT/bin/main")
  1498  }
  1499  
  1500  func TestGbGenerate(t *testing.T) {
  1501  	if runtime.GOOS == "windows" {
  1502  		t.Skipf("windows doesn't have echo, lol")
  1503  	}
  1504  	gb := T{T: t}
  1505  	defer gb.cleanup()
  1506  	gb.tempDir("src/gentest")
  1507  	gb.tempFile("src/gentest/generate.go", `package gentest
  1508  //go:generate echo $GOPACKAGE $GOFILE
  1509  `)
  1510  	gb.cd(gb.tempdir)
  1511  	gb.run("generate")
  1512  	gb.grepStdout("^gentest generate.go$", "expected $GOPACKAGE $GOFILE")
  1513  }
  1514  
  1515  func TestGbDoc(t *testing.T) {
  1516  	if runtime.GOOS == "windows" {
  1517  		t.Skipf("windows doesn't have echo, lol")
  1518  	}
  1519  	gb := T{T: t}
  1520  	defer gb.cleanup()
  1521  	gb.tempDir("src/doctest")
  1522  	gb.tempFile("src/doctest/doc.go", `// Package doctest tests gb doc
  1523  package doctest
  1524  `)
  1525  	gb.cd(gb.tempdir)
  1526  	gb.run("doc", "doctest")
  1527  	gb.grepStdout("Package doctest tests gb doc$", "expected Package doctest tests gb doc")
  1528  }
  1529  
  1530  func TestIssue346(t *testing.T) {
  1531  	gb := T{T: t}
  1532  	defer gb.cleanup()
  1533  	gb.tempDir("src/p")
  1534  	gb.tempFile("src/p/main.go", `package main
  1535  func main() { println("hello world") }
  1536  `)
  1537  	gb.cd(gb.tempdir)
  1538  	tmpdir := gb.tempDir("tmp")
  1539  	gb.setenv("TMP", tmpdir)
  1540  
  1541  	goos := runtime.GOOS
  1542  
  1543  	// scenario 1: GOOS/GOARCH not set
  1544  	name := "p"
  1545  	if goos == "windows" {
  1546  		name += ".exe"
  1547  	}
  1548  	gb.unsetenv("GOOS")
  1549  	gb.unsetenv("GOARCH")
  1550  	gb.run("build")
  1551  	gb.wantExecutable(gb.path("bin", name), "expected $PROJECT/bin/p")
  1552  
  1553  	// scenario 2: GOOS/GOARCH are both set
  1554  	name = fmt.Sprintf("p-%s-%s", goos, runtime.GOARCH)
  1555  	if goos == "windows" {
  1556  		name += ".exe"
  1557  	}
  1558  	gb.setenv("GOOS", goos)
  1559  	gb.setenv("GOARCH", runtime.GOARCH)
  1560  	gb.run("build")
  1561  	gb.wantExecutable(gb.path("bin", name), "expected $PROJECT/bin/p-$GOOS-$GOARCH")
  1562  
  1563  	// scenario 3: just GOOS is set
  1564  	os.Remove(gb.path("bin", name))
  1565  	gb.unsetenv("GOARCH")
  1566  	gb.run("build")
  1567  	gb.mustNotExist(gb.path("bin", name))
  1568  }
  1569  
  1570  func TestGbBuildCannotReferencePackagesInGoroot(t *testing.T) {
  1571  	gb := T{T: t}
  1572  	defer gb.cleanup()
  1573  
  1574  	gb.tempDir("src")
  1575  	gb.cd(gb.tempdir)
  1576  	tmpdir := gb.tempDir("tmp")
  1577  
  1578  	gb.setenv("TMP", tmpdir)
  1579  	gb.runFail("build", "net/http") // net/http will be excluded by resolveRootPackages
  1580  	gb.mustBeEmpty(tmpdir)
  1581  	gb.mustNotExist(gb.path("pkg"))
  1582  	gb.grepStderr(`FATAL: command "build" failed: no packages supplied`, "expected FATAL")
  1583  }
  1584  
  1585  func TestGbBuildWillResolvePackagesInVendorAsRoots(t *testing.T) {
  1586  	gb := T{T: t}
  1587  	defer gb.cleanup()
  1588  
  1589  	gb.tempDir("src")
  1590  	gb.tempDir("vendor/src/test/test1")
  1591  	gb.tempFile("vendor/src/test/test1/test1.go", `package http
  1592  func init() {
  1593          println("Hello, world!")
  1594  }
  1595  `)
  1596  	gb.cd(gb.tempdir)
  1597  	tmpdir := gb.tempDir("tmp")
  1598  
  1599  	gb.setenv("TMP", tmpdir)
  1600  	gb.runFail("build") // should fail, nothing supplied
  1601  	gb.mustBeEmpty(tmpdir)
  1602  	gb.mustNotExist(gb.path("pkg"))
  1603  	gb.grepStderr(`FATAL: command "build" failed: no packages supplied`, "expected FATAL")
  1604  
  1605  	gb.runFail("build", "test/...") // should fail, globbing does not match $PROJECT/vendor/src
  1606  	gb.mustBeEmpty(tmpdir)
  1607  	gb.mustNotExist(gb.path("pkg"))
  1608  	gb.grepStderr(`FATAL: command "build" failed: no packages supplied`, "expected FATAL")
  1609  
  1610  	gb.run("build", "test/test1") // should resolve to vendor/src/test/test1
  1611  	gb.mustBeEmpty(tmpdir)
  1612  	gb.wantArchive(filepath.Join(gb.tempdir, "pkg", runtime.GOOS+"-"+runtime.GOARCH, "test", "test1.a"))
  1613  	gb.grepStdout(`^test/test`, "expected test/test1")
  1614  }
  1615  
  1616  func TestIssue550(t *testing.T) {
  1617  	gb := T{T: t}
  1618  	defer gb.cleanup()
  1619  
  1620  	gb.tempDir("src/x")
  1621  	gb.tempFile("src/x/x.go", `package main
  1622  
  1623  import (
  1624      "log"
  1625      "this/is/a/bad/path"
  1626  )
  1627  
  1628  func main() {
  1629      log.Println("Hello World.")
  1630  }
  1631  `)
  1632  	gb.cd(gb.tempdir)
  1633  	tmpdir := gb.tempDir("tmp")
  1634  
  1635  	gb.setenv("TMP", tmpdir)
  1636  	gb.runFail("build")
  1637  	gb.mustBeEmpty(tmpdir)
  1638  	gb.grepStderr(`FATAL: command "build" failed: failed to resolve import path "x": import "this/is/a/bad/path": not found`, "expected FATAL")
  1639  }
  1640  
  1641  func TestIssue530(t *testing.T) {
  1642  	gb := T{T: t}
  1643  	defer gb.cleanup()
  1644  
  1645  	gb.tempDir("src/main")
  1646  	gb.tempFile("src/main/main.go", `package main
  1647  
  1648  import "fmt"
  1649  
  1650  func main() {
  1651  	fmt.Println("hello gb")
  1652  }
  1653  `)
  1654  
  1655  	gb.cd(gb.tempdir)
  1656  	tmpdir := gb.tempDir("tmp")
  1657  	gb.run("build")
  1658  	gb.mustBeEmpty(tmpdir)
  1659  }
  1660  
  1661  // goconvey (and probably others) do not parse flags passed to the
  1662  // test binary, they just expect them to be present in their raw form
  1663  // in os.Args. As such -test.v and -test.v=true are not the same.
  1664  // Assert that gb is passing the latter form.
  1665  func TestIssue605(t *testing.T) {
  1666  	gb := T{T: t}
  1667  	defer gb.cleanup()
  1668  
  1669  	gb.tempDir("src/issue605")
  1670  	gb.tempFile("src/issue605/issue_test.go", `package issue605
  1671  
  1672  import (
  1673          "os"
  1674          "testing"
  1675  )
  1676  
  1677  func TestFlags(t *testing.T) {
  1678          for _, f := range os.Args {
  1679                  if f == "-test.v=true" {
  1680                          return
  1681                  }
  1682          }
  1683          t.Fatalf("could not find test flag: %q", os.Args)
  1684  }`)
  1685  	gb.cd(gb.tempdir)
  1686  	tmpdir := gb.tempDir("tmp")
  1687  	gb.run("test", "-v") // should translate into -test.v=true
  1688  	gb.mustBeEmpty(tmpdir)
  1689  
  1690  }
  1691  
  1692  // assert the gb build all alias works.
  1693  func TestBuildAll(t *testing.T) {
  1694  	gb := T{T: t}
  1695  	defer gb.cleanup()
  1696  
  1697  	gb.tempFile("src/pkg1/main.go", `package main
  1698  
  1699  import "fmt"
  1700  
  1701  func main() {
  1702  	fmt.Println("hello")
  1703  }`)
  1704  	gb.tempFile("src/pkg2/main.go", `package main
  1705  
  1706  import "fmt"
  1707  
  1708  func main() {
  1709          fmt.Println("hello")
  1710  }`)
  1711  
  1712  	gb.cd(filepath.Join(gb.tempdir, "src/pkg2"))
  1713  	tmpdir := gb.tempDir("tmp")
  1714  	gb.run("build", "all")
  1715  	gb.grepStdout("^pkg1$", "expected pkg1")
  1716  	gb.grepStdout("^pkg2$", "expected pkg2")
  1717  	gb.mustBeEmpty(tmpdir)
  1718  }
  1719  
  1720  func TestIssue680(t *testing.T) {
  1721  	gb := T{T: t}
  1722  	defer gb.cleanup()
  1723  
  1724  	gb.tempFile("src/issue680/issue_test.go", `// +build go1.7
  1725  
  1726  package main
  1727  
  1728  import (
  1729  	"net/http/httptest"
  1730  	"testing"
  1731  )
  1732  
  1733  func TestFoo(t *testing.T) {
  1734  	_ = httptest.NewRequest("", "https://example.com", nil)
  1735  }`)
  1736  	gb.tempFile("src/issue680/test_test.go", "package main")
  1737  
  1738  	gb.cd(gb.tempdir)
  1739  	tmpdir := gb.tempDir("tmp")
  1740  	gb.run("test")
  1741  	gb.mustBeEmpty(tmpdir)
  1742  }