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