Black Lives Matter. Support the Equal Justice Initiative.

Source file src/cmd/go/go_test.go

Documentation: cmd/go

     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  import (
     8  	"bytes"
     9  	"debug/elf"
    10  	"debug/macho"
    11  	"debug/pe"
    12  	"encoding/binary"
    13  	"flag"
    14  	"fmt"
    15  	"go/format"
    16  	"internal/race"
    17  	"internal/testenv"
    18  	"io"
    19  	"io/fs"
    20  	"log"
    21  	"os"
    22  	"os/exec"
    23  	"path/filepath"
    24  	"regexp"
    25  	"runtime"
    26  	"strconv"
    27  	"strings"
    28  	"testing"
    29  	"time"
    30  
    31  	"cmd/go/internal/cache"
    32  	"cmd/go/internal/cfg"
    33  	"cmd/go/internal/robustio"
    34  	"cmd/go/internal/work"
    35  	"cmd/internal/sys"
    36  )
    37  
    38  func init() {
    39  	// GOVCS defaults to public:git|hg,private:all,
    40  	// which breaks many tests here - they can't use non-git, non-hg VCS at all!
    41  	// Change to fully permissive.
    42  	// The tests of the GOVCS setting itself are in ../../testdata/script/govcs.txt.
    43  	os.Setenv("GOVCS", "*:all")
    44  }
    45  
    46  var (
    47  	canRace = false // whether we can run the race detector
    48  	canCgo  = false // whether we can use cgo
    49  	canMSan = false // whether we can run the memory sanitizer
    50  )
    51  
    52  var exeSuffix string = func() string {
    53  	if runtime.GOOS == "windows" {
    54  		return ".exe"
    55  	}
    56  	return ""
    57  }()
    58  
    59  func tooSlow(t *testing.T) {
    60  	if testing.Short() {
    61  		// In -short mode; skip test, except run it on the {darwin,linux,windows}/amd64 builders.
    62  		if testenv.Builder() != "" && runtime.GOARCH == "amd64" && (runtime.GOOS == "linux" || runtime.GOOS == "darwin" || runtime.GOOS == "windows") {
    63  			return
    64  		}
    65  		t.Helper()
    66  		t.Skip("skipping test in -short mode")
    67  	}
    68  }
    69  
    70  // testGOROOT is the GOROOT to use when running testgo, a cmd/go binary
    71  // build from this process's current GOROOT, but run from a different
    72  // (temp) directory.
    73  var testGOROOT string
    74  
    75  var testGOCACHE string
    76  
    77  var testGo string
    78  var testTmpDir string
    79  var testBin string
    80  
    81  // The TestMain function creates a go command for testing purposes and
    82  // deletes it after the tests have been run.
    83  func TestMain(m *testing.M) {
    84  	// $GO_GCFLAGS a compiler debug flag known to cmd/dist, make.bash, etc.
    85  	// It is not a standard go command flag; use os.Getenv, not cfg.Getenv.
    86  	if os.Getenv("GO_GCFLAGS") != "" {
    87  		fmt.Fprintf(os.Stderr, "testing: warning: no tests to run\n") // magic string for cmd/go
    88  		fmt.Printf("cmd/go test is not compatible with $GO_GCFLAGS being set\n")
    89  		fmt.Printf("SKIP\n")
    90  		return
    91  	}
    92  
    93  	flag.Parse()
    94  
    95  	if *proxyAddr != "" {
    96  		StartProxy()
    97  		select {}
    98  	}
    99  
   100  	// Run with a temporary TMPDIR to check that the tests don't
   101  	// leave anything behind.
   102  	topTmpdir, err := os.MkdirTemp("", "cmd-go-test-")
   103  	if err != nil {
   104  		log.Fatal(err)
   105  	}
   106  	if !*testWork {
   107  		defer removeAll(topTmpdir)
   108  	}
   109  	os.Setenv(tempEnvName(), topTmpdir)
   110  
   111  	dir, err := os.MkdirTemp(topTmpdir, "tmpdir")
   112  	if err != nil {
   113  		log.Fatal(err)
   114  	}
   115  	testTmpDir = dir
   116  	if !*testWork {
   117  		defer removeAll(testTmpDir)
   118  	}
   119  
   120  	testGOCACHE = cache.DefaultDir()
   121  	if testenv.HasGoBuild() {
   122  		testBin = filepath.Join(testTmpDir, "testbin")
   123  		if err := os.Mkdir(testBin, 0777); err != nil {
   124  			log.Fatal(err)
   125  		}
   126  		testGo = filepath.Join(testBin, "go"+exeSuffix)
   127  		args := []string{"build", "-tags", "testgo", "-o", testGo}
   128  		if race.Enabled {
   129  			args = append(args, "-race")
   130  		}
   131  		gotool, err := testenv.GoTool()
   132  		if err != nil {
   133  			fmt.Fprintln(os.Stderr, err)
   134  			os.Exit(2)
   135  		}
   136  
   137  		goEnv := func(name string) string {
   138  			out, err := exec.Command(gotool, "env", name).CombinedOutput()
   139  			if err != nil {
   140  				fmt.Fprintf(os.Stderr, "go env %s: %v\n%s", name, err, out)
   141  				os.Exit(2)
   142  			}
   143  			return strings.TrimSpace(string(out))
   144  		}
   145  		testGOROOT = goEnv("GOROOT")
   146  		os.Setenv("TESTGO_GOROOT", testGOROOT)
   147  		// Ensure that GOROOT is set explicitly.
   148  		// Otherwise, if the toolchain was built with GOROOT_FINAL set but has not
   149  		// yet been moved to its final location, programs that invoke runtime.GOROOT
   150  		// may accidentally use the wrong path.
   151  		os.Setenv("GOROOT", testGOROOT)
   152  
   153  		// The whole GOROOT/pkg tree was installed using the GOHOSTOS/GOHOSTARCH
   154  		// toolchain (installed in GOROOT/pkg/tool/GOHOSTOS_GOHOSTARCH).
   155  		// The testgo.exe we are about to create will be built for GOOS/GOARCH,
   156  		// which means it will use the GOOS/GOARCH toolchain
   157  		// (installed in GOROOT/pkg/tool/GOOS_GOARCH).
   158  		// If these are not the same toolchain, then the entire standard library
   159  		// will look out of date (the compilers in those two different tool directories
   160  		// are built for different architectures and have different build IDs),
   161  		// which will cause many tests to do unnecessary rebuilds and some
   162  		// tests to attempt to overwrite the installed standard library.
   163  		// Bail out entirely in this case.
   164  		hostGOOS := goEnv("GOHOSTOS")
   165  		hostGOARCH := goEnv("GOHOSTARCH")
   166  		if hostGOOS != runtime.GOOS || hostGOARCH != runtime.GOARCH {
   167  			fmt.Fprintf(os.Stderr, "testing: warning: no tests to run\n") // magic string for cmd/go
   168  			fmt.Printf("cmd/go test is not compatible with GOOS/GOARCH != GOHOSTOS/GOHOSTARCH (%s/%s != %s/%s)\n", runtime.GOOS, runtime.GOARCH, hostGOOS, hostGOARCH)
   169  			fmt.Printf("SKIP\n")
   170  			return
   171  		}
   172  
   173  		buildCmd := exec.Command(gotool, args...)
   174  		buildCmd.Env = append(os.Environ(), "GOFLAGS=-mod=vendor")
   175  		out, err := buildCmd.CombinedOutput()
   176  		if err != nil {
   177  			fmt.Fprintf(os.Stderr, "building testgo failed: %v\n%s", err, out)
   178  			os.Exit(2)
   179  		}
   180  
   181  		cmd := exec.Command(testGo, "env", "CGO_ENABLED")
   182  		cmd.Stderr = new(strings.Builder)
   183  		if out, err := cmd.Output(); err != nil {
   184  			fmt.Fprintf(os.Stderr, "running testgo failed: %v\n%s", err, cmd.Stderr)
   185  			os.Exit(2)
   186  		} else {
   187  			canCgo, err = strconv.ParseBool(strings.TrimSpace(string(out)))
   188  			if err != nil {
   189  				fmt.Fprintf(os.Stderr, "can't parse go env CGO_ENABLED output: %v\n", strings.TrimSpace(string(out)))
   190  			}
   191  		}
   192  
   193  		out, err = exec.Command(gotool, "env", "GOCACHE").CombinedOutput()
   194  		if err != nil {
   195  			fmt.Fprintf(os.Stderr, "could not find testing GOCACHE: %v\n%s", err, out)
   196  			os.Exit(2)
   197  		}
   198  		testGOCACHE = strings.TrimSpace(string(out))
   199  
   200  		canMSan = canCgo && sys.MSanSupported(runtime.GOOS, runtime.GOARCH)
   201  		canRace = canCgo && sys.RaceDetectorSupported(runtime.GOOS, runtime.GOARCH)
   202  		// The race detector doesn't work on Alpine Linux:
   203  		// golang.org/issue/14481
   204  		// gccgo does not support the race detector.
   205  		if isAlpineLinux() || runtime.Compiler == "gccgo" {
   206  			canRace = false
   207  		}
   208  	}
   209  	// Don't let these environment variables confuse the test.
   210  	os.Setenv("GOENV", "off")
   211  	os.Unsetenv("GOFLAGS")
   212  	os.Unsetenv("GOBIN")
   213  	os.Unsetenv("GOPATH")
   214  	os.Unsetenv("GIT_ALLOW_PROTOCOL")
   215  	os.Setenv("HOME", "/test-go-home-does-not-exist")
   216  	// On some systems the default C compiler is ccache.
   217  	// Setting HOME to a non-existent directory will break
   218  	// those systems. Disable ccache and use real compiler. Issue 17668.
   219  	os.Setenv("CCACHE_DISABLE", "1")
   220  	if cfg.Getenv("GOCACHE") == "" {
   221  		os.Setenv("GOCACHE", testGOCACHE) // because $HOME is gone
   222  	}
   223  
   224  	r := m.Run()
   225  	if !*testWork {
   226  		removeAll(testTmpDir) // os.Exit won't run defer
   227  	}
   228  
   229  	if !*testWork {
   230  		// There shouldn't be anything left in topTmpdir.
   231  		dirf, err := os.Open(topTmpdir)
   232  		if err != nil {
   233  			log.Fatal(err)
   234  		}
   235  		names, err := dirf.Readdirnames(0)
   236  		if err != nil {
   237  			log.Fatal(err)
   238  		}
   239  		if len(names) > 0 {
   240  			log.Fatalf("unexpected files left in tmpdir: %v", names)
   241  		}
   242  
   243  		removeAll(topTmpdir)
   244  	}
   245  
   246  	os.Exit(r)
   247  }
   248  
   249  func isAlpineLinux() bool {
   250  	if runtime.GOOS != "linux" {
   251  		return false
   252  	}
   253  	fi, err := os.Lstat("/etc/alpine-release")
   254  	return err == nil && fi.Mode().IsRegular()
   255  }
   256  
   257  // The length of an mtime tick on this system. This is an estimate of
   258  // how long we need to sleep to ensure that the mtime of two files is
   259  // different.
   260  // We used to try to be clever but that didn't always work (see golang.org/issue/12205).
   261  var mtimeTick time.Duration = 1 * time.Second
   262  
   263  // Manage a single run of the testgo binary.
   264  type testgoData struct {
   265  	t              *testing.T
   266  	temps          []string
   267  	env            []string
   268  	tempdir        string
   269  	ran            bool
   270  	inParallel     bool
   271  	stdout, stderr bytes.Buffer
   272  	execDir        string // dir for tg.run
   273  }
   274  
   275  // skipIfGccgo skips the test if using gccgo.
   276  func skipIfGccgo(t *testing.T, msg string) {
   277  	if runtime.Compiler == "gccgo" {
   278  		t.Skipf("skipping test not supported on gccgo: %s", msg)
   279  	}
   280  }
   281  
   282  // testgo sets up for a test that runs testgo.
   283  func testgo(t *testing.T) *testgoData {
   284  	t.Helper()
   285  	testenv.MustHaveGoBuild(t)
   286  	testenv.SkipIfShortAndSlow(t)
   287  
   288  	return &testgoData{t: t}
   289  }
   290  
   291  // must gives a fatal error if err is not nil.
   292  func (tg *testgoData) must(err error) {
   293  	tg.t.Helper()
   294  	if err != nil {
   295  		tg.t.Fatal(err)
   296  	}
   297  }
   298  
   299  // check gives a test non-fatal error if err is not nil.
   300  func (tg *testgoData) check(err error) {
   301  	tg.t.Helper()
   302  	if err != nil {
   303  		tg.t.Error(err)
   304  	}
   305  }
   306  
   307  // parallel runs the test in parallel by calling t.Parallel.
   308  func (tg *testgoData) parallel() {
   309  	tg.t.Helper()
   310  	if tg.ran {
   311  		tg.t.Fatal("internal testsuite error: call to parallel after run")
   312  	}
   313  	for _, e := range tg.env {
   314  		if strings.HasPrefix(e, "GOROOT=") || strings.HasPrefix(e, "GOPATH=") || strings.HasPrefix(e, "GOBIN=") {
   315  			val := e[strings.Index(e, "=")+1:]
   316  			if strings.HasPrefix(val, "testdata") || strings.HasPrefix(val, "./testdata") {
   317  				tg.t.Fatalf("internal testsuite error: call to parallel with testdata in environment (%s)", e)
   318  			}
   319  		}
   320  	}
   321  	tg.inParallel = true
   322  	tg.t.Parallel()
   323  }
   324  
   325  // pwd returns the current directory.
   326  func (tg *testgoData) pwd() string {
   327  	tg.t.Helper()
   328  	wd, err := os.Getwd()
   329  	if err != nil {
   330  		tg.t.Fatalf("could not get working directory: %v", err)
   331  	}
   332  	return wd
   333  }
   334  
   335  // sleep sleeps for one tick, where a tick is a conservative estimate
   336  // of how long it takes for a file modification to get a different
   337  // mtime.
   338  func (tg *testgoData) sleep() {
   339  	time.Sleep(mtimeTick)
   340  }
   341  
   342  // setenv sets an environment variable to use when running the test go
   343  // command.
   344  func (tg *testgoData) setenv(name, val string) {
   345  	tg.t.Helper()
   346  	if tg.inParallel && (name == "GOROOT" || name == "GOPATH" || name == "GOBIN") && (strings.HasPrefix(val, "testdata") || strings.HasPrefix(val, "./testdata")) {
   347  		tg.t.Fatalf("internal testsuite error: call to setenv with testdata (%s=%s) after parallel", name, val)
   348  	}
   349  	tg.unsetenv(name)
   350  	tg.env = append(tg.env, name+"="+val)
   351  }
   352  
   353  // unsetenv removes an environment variable.
   354  func (tg *testgoData) unsetenv(name string) {
   355  	if tg.env == nil {
   356  		tg.env = append([]string(nil), os.Environ()...)
   357  		tg.env = append(tg.env, "GO111MODULE=off")
   358  	}
   359  	for i, v := range tg.env {
   360  		if strings.HasPrefix(v, name+"=") {
   361  			tg.env = append(tg.env[:i], tg.env[i+1:]...)
   362  			break
   363  		}
   364  	}
   365  }
   366  
   367  func (tg *testgoData) goTool() string {
   368  	return testGo
   369  }
   370  
   371  // doRun runs the test go command, recording stdout and stderr and
   372  // returning exit status.
   373  func (tg *testgoData) doRun(args []string) error {
   374  	tg.t.Helper()
   375  	if tg.inParallel {
   376  		for _, arg := range args {
   377  			if strings.HasPrefix(arg, "testdata") || strings.HasPrefix(arg, "./testdata") {
   378  				tg.t.Fatal("internal testsuite error: parallel run using testdata")
   379  			}
   380  		}
   381  	}
   382  
   383  	hasGoroot := false
   384  	for _, v := range tg.env {
   385  		if strings.HasPrefix(v, "GOROOT=") {
   386  			hasGoroot = true
   387  			break
   388  		}
   389  	}
   390  	prog := tg.goTool()
   391  	if !hasGoroot {
   392  		tg.setenv("GOROOT", testGOROOT)
   393  	}
   394  
   395  	tg.t.Logf("running testgo %v", args)
   396  	cmd := exec.Command(prog, args...)
   397  	tg.stdout.Reset()
   398  	tg.stderr.Reset()
   399  	cmd.Dir = tg.execDir
   400  	cmd.Stdout = &tg.stdout
   401  	cmd.Stderr = &tg.stderr
   402  	cmd.Env = tg.env
   403  	status := cmd.Run()
   404  	if tg.stdout.Len() > 0 {
   405  		tg.t.Log("standard output:")
   406  		tg.t.Log(tg.stdout.String())
   407  	}
   408  	if tg.stderr.Len() > 0 {
   409  		tg.t.Log("standard error:")
   410  		tg.t.Log(tg.stderr.String())
   411  	}
   412  	tg.ran = true
   413  	return status
   414  }
   415  
   416  // run runs the test go command, and expects it to succeed.
   417  func (tg *testgoData) run(args ...string) {
   418  	tg.t.Helper()
   419  	if status := tg.doRun(args); status != nil {
   420  		wd, _ := os.Getwd()
   421  		tg.t.Logf("go %v failed unexpectedly in %s: %v", args, wd, status)
   422  		tg.t.FailNow()
   423  	}
   424  }
   425  
   426  // runFail runs the test go command, and expects it to fail.
   427  func (tg *testgoData) runFail(args ...string) {
   428  	tg.t.Helper()
   429  	if status := tg.doRun(args); status == nil {
   430  		tg.t.Fatal("testgo succeeded unexpectedly")
   431  	} else {
   432  		tg.t.Log("testgo failed as expected:", status)
   433  	}
   434  }
   435  
   436  // runGit runs a git command, and expects it to succeed.
   437  func (tg *testgoData) runGit(dir string, args ...string) {
   438  	tg.t.Helper()
   439  	cmd := exec.Command("git", args...)
   440  	tg.stdout.Reset()
   441  	tg.stderr.Reset()
   442  	cmd.Stdout = &tg.stdout
   443  	cmd.Stderr = &tg.stderr
   444  	cmd.Dir = dir
   445  	cmd.Env = tg.env
   446  	status := cmd.Run()
   447  	if tg.stdout.Len() > 0 {
   448  		tg.t.Log("git standard output:")
   449  		tg.t.Log(tg.stdout.String())
   450  	}
   451  	if tg.stderr.Len() > 0 {
   452  		tg.t.Log("git standard error:")
   453  		tg.t.Log(tg.stderr.String())
   454  	}
   455  	if status != nil {
   456  		tg.t.Logf("git %v failed unexpectedly: %v", args, status)
   457  		tg.t.FailNow()
   458  	}
   459  }
   460  
   461  // getStdout returns standard output of the testgo run as a string.
   462  func (tg *testgoData) getStdout() string {
   463  	tg.t.Helper()
   464  	if !tg.ran {
   465  		tg.t.Fatal("internal testsuite error: stdout called before run")
   466  	}
   467  	return tg.stdout.String()
   468  }
   469  
   470  // getStderr returns standard error of the testgo run as a string.
   471  func (tg *testgoData) getStderr() string {
   472  	tg.t.Helper()
   473  	if !tg.ran {
   474  		tg.t.Fatal("internal testsuite error: stdout called before run")
   475  	}
   476  	return tg.stderr.String()
   477  }
   478  
   479  // doGrepMatch looks for a regular expression in a buffer, and returns
   480  // whether it is found. The regular expression is matched against
   481  // each line separately, as with the grep command.
   482  func (tg *testgoData) doGrepMatch(match string, b *bytes.Buffer) bool {
   483  	tg.t.Helper()
   484  	if !tg.ran {
   485  		tg.t.Fatal("internal testsuite error: grep called before run")
   486  	}
   487  	re := regexp.MustCompile(match)
   488  	for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) {
   489  		if re.Match(ln) {
   490  			return true
   491  		}
   492  	}
   493  	return false
   494  }
   495  
   496  // doGrep looks for a regular expression in a buffer and fails if it
   497  // is not found. The name argument is the name of the output we are
   498  // searching, "output" or "error". The msg argument is logged on
   499  // failure.
   500  func (tg *testgoData) doGrep(match string, b *bytes.Buffer, name, msg string) {
   501  	tg.t.Helper()
   502  	if !tg.doGrepMatch(match, b) {
   503  		tg.t.Log(msg)
   504  		tg.t.Logf("pattern %v not found in standard %s", match, name)
   505  		tg.t.FailNow()
   506  	}
   507  }
   508  
   509  // grepStdout looks for a regular expression in the test run's
   510  // standard output and fails, logging msg, if it is not found.
   511  func (tg *testgoData) grepStdout(match, msg string) {
   512  	tg.t.Helper()
   513  	tg.doGrep(match, &tg.stdout, "output", msg)
   514  }
   515  
   516  // grepStderr looks for a regular expression in the test run's
   517  // standard error and fails, logging msg, if it is not found.
   518  func (tg *testgoData) grepStderr(match, msg string) {
   519  	tg.t.Helper()
   520  	tg.doGrep(match, &tg.stderr, "error", msg)
   521  }
   522  
   523  // grepBoth looks for a regular expression in the test run's standard
   524  // output or stand error and fails, logging msg, if it is not found.
   525  func (tg *testgoData) grepBoth(match, msg string) {
   526  	tg.t.Helper()
   527  	if !tg.doGrepMatch(match, &tg.stdout) && !tg.doGrepMatch(match, &tg.stderr) {
   528  		tg.t.Log(msg)
   529  		tg.t.Logf("pattern %v not found in standard output or standard error", match)
   530  		tg.t.FailNow()
   531  	}
   532  }
   533  
   534  // doGrepNot looks for a regular expression in a buffer and fails if
   535  // it is found. The name and msg arguments are as for doGrep.
   536  func (tg *testgoData) doGrepNot(match string, b *bytes.Buffer, name, msg string) {
   537  	tg.t.Helper()
   538  	if tg.doGrepMatch(match, b) {
   539  		tg.t.Log(msg)
   540  		tg.t.Logf("pattern %v found unexpectedly in standard %s", match, name)
   541  		tg.t.FailNow()
   542  	}
   543  }
   544  
   545  // grepStdoutNot looks for a regular expression in the test run's
   546  // standard output and fails, logging msg, if it is found.
   547  func (tg *testgoData) grepStdoutNot(match, msg string) {
   548  	tg.t.Helper()
   549  	tg.doGrepNot(match, &tg.stdout, "output", msg)
   550  }
   551  
   552  // grepStderrNot looks for a regular expression in the test run's
   553  // standard error and fails, logging msg, if it is found.
   554  func (tg *testgoData) grepStderrNot(match, msg string) {
   555  	tg.t.Helper()
   556  	tg.doGrepNot(match, &tg.stderr, "error", msg)
   557  }
   558  
   559  // grepBothNot looks for a regular expression in the test run's
   560  // standard output or standard error and fails, logging msg, if it is
   561  // found.
   562  func (tg *testgoData) grepBothNot(match, msg string) {
   563  	tg.t.Helper()
   564  	if tg.doGrepMatch(match, &tg.stdout) || tg.doGrepMatch(match, &tg.stderr) {
   565  		tg.t.Log(msg)
   566  		tg.t.Fatalf("pattern %v found unexpectedly in standard output or standard error", match)
   567  	}
   568  }
   569  
   570  // doGrepCount counts the number of times a regexp is seen in a buffer.
   571  func (tg *testgoData) doGrepCount(match string, b *bytes.Buffer) int {
   572  	tg.t.Helper()
   573  	if !tg.ran {
   574  		tg.t.Fatal("internal testsuite error: doGrepCount called before run")
   575  	}
   576  	re := regexp.MustCompile(match)
   577  	c := 0
   578  	for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) {
   579  		if re.Match(ln) {
   580  			c++
   581  		}
   582  	}
   583  	return c
   584  }
   585  
   586  // grepCountBoth returns the number of times a regexp is seen in both
   587  // standard output and standard error.
   588  func (tg *testgoData) grepCountBoth(match string) int {
   589  	tg.t.Helper()
   590  	return tg.doGrepCount(match, &tg.stdout) + tg.doGrepCount(match, &tg.stderr)
   591  }
   592  
   593  // creatingTemp records that the test plans to create a temporary file
   594  // or directory. If the file or directory exists already, it will be
   595  // removed. When the test completes, the file or directory will be
   596  // removed if it exists.
   597  func (tg *testgoData) creatingTemp(path string) {
   598  	tg.t.Helper()
   599  	if filepath.IsAbs(path) && !strings.HasPrefix(path, tg.tempdir) {
   600  		tg.t.Fatalf("internal testsuite error: creatingTemp(%q) with absolute path not in temporary directory", path)
   601  	}
   602  	tg.must(robustio.RemoveAll(path))
   603  	tg.temps = append(tg.temps, path)
   604  }
   605  
   606  // makeTempdir makes a temporary directory for a run of testgo. If
   607  // the temporary directory was already created, this does nothing.
   608  func (tg *testgoData) makeTempdir() {
   609  	tg.t.Helper()
   610  	if tg.tempdir == "" {
   611  		var err error
   612  		tg.tempdir, err = os.MkdirTemp("", "gotest")
   613  		tg.must(err)
   614  	}
   615  }
   616  
   617  // tempFile adds a temporary file for a run of testgo.
   618  func (tg *testgoData) tempFile(path, contents string) {
   619  	tg.t.Helper()
   620  	tg.makeTempdir()
   621  	tg.must(os.MkdirAll(filepath.Join(tg.tempdir, filepath.Dir(path)), 0755))
   622  	bytes := []byte(contents)
   623  	if strings.HasSuffix(path, ".go") {
   624  		formatted, err := format.Source(bytes)
   625  		if err == nil {
   626  			bytes = formatted
   627  		}
   628  	}
   629  	tg.must(os.WriteFile(filepath.Join(tg.tempdir, path), bytes, 0644))
   630  }
   631  
   632  // tempDir adds a temporary directory for a run of testgo.
   633  func (tg *testgoData) tempDir(path string) {
   634  	tg.t.Helper()
   635  	tg.makeTempdir()
   636  	if err := os.MkdirAll(filepath.Join(tg.tempdir, path), 0755); err != nil && !os.IsExist(err) {
   637  		tg.t.Fatal(err)
   638  	}
   639  }
   640  
   641  // path returns the absolute pathname to file with the temporary
   642  // directory.
   643  func (tg *testgoData) path(name string) string {
   644  	tg.t.Helper()
   645  	if tg.tempdir == "" {
   646  		tg.t.Fatalf("internal testsuite error: path(%q) with no tempdir", name)
   647  	}
   648  	if name == "." {
   649  		return tg.tempdir
   650  	}
   651  	return filepath.Join(tg.tempdir, name)
   652  }
   653  
   654  // mustExist fails if path does not exist.
   655  func (tg *testgoData) mustExist(path string) {
   656  	tg.t.Helper()
   657  	if _, err := os.Stat(path); err != nil {
   658  		if os.IsNotExist(err) {
   659  			tg.t.Fatalf("%s does not exist but should", path)
   660  		}
   661  		tg.t.Fatalf("%s stat failed: %v", path, err)
   662  	}
   663  }
   664  
   665  // mustNotExist fails if path exists.
   666  func (tg *testgoData) mustNotExist(path string) {
   667  	tg.t.Helper()
   668  	if _, err := os.Stat(path); err == nil || !os.IsNotExist(err) {
   669  		tg.t.Fatalf("%s exists but should not (%v)", path, err)
   670  	}
   671  }
   672  
   673  // mustHaveContent succeeds if filePath is a path to a file,
   674  // and that file is readable and not empty.
   675  func (tg *testgoData) mustHaveContent(filePath string) {
   676  	tg.mustExist(filePath)
   677  	f, err := os.Stat(filePath)
   678  	if err != nil {
   679  		tg.t.Fatal(err)
   680  	}
   681  	if f.Size() == 0 {
   682  		tg.t.Fatalf("expected %s to have data, but is empty", filePath)
   683  	}
   684  }
   685  
   686  // wantExecutable fails with msg if path is not executable.
   687  func (tg *testgoData) wantExecutable(path, msg string) {
   688  	tg.t.Helper()
   689  	if st, err := os.Stat(path); err != nil {
   690  		if !os.IsNotExist(err) {
   691  			tg.t.Log(err)
   692  		}
   693  		tg.t.Fatal(msg)
   694  	} else {
   695  		if runtime.GOOS != "windows" && st.Mode()&0111 == 0 {
   696  			tg.t.Fatalf("binary %s exists but is not executable", path)
   697  		}
   698  	}
   699  }
   700  
   701  // isStale reports whether pkg is stale, and why
   702  func (tg *testgoData) isStale(pkg string) (bool, string) {
   703  	tg.t.Helper()
   704  	tg.run("list", "-f", "{{.Stale}}:{{.StaleReason}}", pkg)
   705  	v := strings.TrimSpace(tg.getStdout())
   706  	f := strings.SplitN(v, ":", 2)
   707  	if len(f) == 2 {
   708  		switch f[0] {
   709  		case "true":
   710  			return true, f[1]
   711  		case "false":
   712  			return false, f[1]
   713  		}
   714  	}
   715  	tg.t.Fatalf("unexpected output checking staleness of package %v: %v", pkg, v)
   716  	panic("unreachable")
   717  }
   718  
   719  // wantStale fails with msg if pkg is not stale.
   720  func (tg *testgoData) wantStale(pkg, reason, msg string) {
   721  	tg.t.Helper()
   722  	stale, why := tg.isStale(pkg)
   723  	if !stale {
   724  		tg.t.Fatal(msg)
   725  	}
   726  	// We always accept the reason as being "not installed but
   727  	// available in build cache", because when that is the case go
   728  	// list doesn't try to sort out the underlying reason why the
   729  	// package is not installed.
   730  	if reason == "" && why != "" || !strings.Contains(why, reason) && !strings.Contains(why, "not installed but available in build cache") {
   731  		tg.t.Errorf("wrong reason for Stale=true: %q, want %q", why, reason)
   732  	}
   733  }
   734  
   735  // wantNotStale fails with msg if pkg is stale.
   736  func (tg *testgoData) wantNotStale(pkg, reason, msg string) {
   737  	tg.t.Helper()
   738  	stale, why := tg.isStale(pkg)
   739  	if stale {
   740  		tg.t.Fatal(msg)
   741  	}
   742  	if reason == "" && why != "" || !strings.Contains(why, reason) {
   743  		tg.t.Errorf("wrong reason for Stale=false: %q, want %q", why, reason)
   744  	}
   745  }
   746  
   747  // If -testwork is specified, the test prints the name of the temp directory
   748  // and does not remove it when done, so that a programmer can
   749  // poke at the test file tree afterward.
   750  var testWork = flag.Bool("testwork", false, "")
   751  
   752  // cleanup cleans up a test that runs testgo.
   753  func (tg *testgoData) cleanup() {
   754  	tg.t.Helper()
   755  	if *testWork {
   756  		tg.t.Logf("TESTWORK=%s\n", tg.path("."))
   757  		return
   758  	}
   759  	for _, path := range tg.temps {
   760  		tg.check(removeAll(path))
   761  	}
   762  	if tg.tempdir != "" {
   763  		tg.check(removeAll(tg.tempdir))
   764  	}
   765  }
   766  
   767  func removeAll(dir string) error {
   768  	// module cache has 0444 directories;
   769  	// make them writable in order to remove content.
   770  	filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error {
   771  		// chmod not only directories, but also things that we couldn't even stat
   772  		// due to permission errors: they may also be unreadable directories.
   773  		if err != nil || info.IsDir() {
   774  			os.Chmod(path, 0777)
   775  		}
   776  		return nil
   777  	})
   778  	return robustio.RemoveAll(dir)
   779  }
   780  
   781  // failSSH puts an ssh executable in the PATH that always fails.
   782  // This is to stub out uses of ssh by go get.
   783  func (tg *testgoData) failSSH() {
   784  	tg.t.Helper()
   785  	wd, err := os.Getwd()
   786  	if err != nil {
   787  		tg.t.Fatal(err)
   788  	}
   789  	fail := filepath.Join(wd, "testdata/failssh")
   790  	tg.setenv("PATH", fmt.Sprintf("%v%c%v", fail, filepath.ListSeparator, os.Getenv("PATH")))
   791  }
   792  
   793  func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
   794  	if testing.Short() {
   795  		t.Skip("skipping lengthy test in short mode")
   796  	}
   797  
   798  	tg := testgo(t)
   799  	defer tg.cleanup()
   800  	tg.parallel()
   801  
   802  	// Copy the runtime packages into a temporary GOROOT
   803  	// so that we can change files.
   804  	for _, copydir := range []string{
   805  		"src/runtime",
   806  		"src/internal/abi",
   807  		"src/internal/bytealg",
   808  		"src/internal/cpu",
   809  		"src/internal/goexperiment",
   810  		"src/math/bits",
   811  		"src/unsafe",
   812  		filepath.Join("pkg", runtime.GOOS+"_"+runtime.GOARCH),
   813  		filepath.Join("pkg/tool", runtime.GOOS+"_"+runtime.GOARCH),
   814  		"pkg/include",
   815  	} {
   816  		srcdir := filepath.Join(testGOROOT, copydir)
   817  		tg.tempDir(filepath.Join("goroot", copydir))
   818  		err := filepath.WalkDir(srcdir,
   819  			func(path string, info fs.DirEntry, err error) error {
   820  				if err != nil {
   821  					return err
   822  				}
   823  				if info.IsDir() {
   824  					return nil
   825  				}
   826  				srcrel, err := filepath.Rel(srcdir, path)
   827  				if err != nil {
   828  					return err
   829  				}
   830  				dest := filepath.Join("goroot", copydir, srcrel)
   831  				data, err := os.ReadFile(path)
   832  				if err != nil {
   833  					return err
   834  				}
   835  				tg.tempFile(dest, string(data))
   836  				if strings.Contains(copydir, filepath.Join("pkg", "tool")) {
   837  					os.Chmod(tg.path(dest), 0777)
   838  				}
   839  				return nil
   840  			})
   841  		if err != nil {
   842  			t.Fatal(err)
   843  		}
   844  	}
   845  	tg.setenv("GOROOT", tg.path("goroot"))
   846  
   847  	addVar := func(name string, idx int) (restore func()) {
   848  		data, err := os.ReadFile(name)
   849  		if err != nil {
   850  			t.Fatal(err)
   851  		}
   852  		old := data
   853  		data = append(data, fmt.Sprintf("var DummyUnusedVar%d bool\n", idx)...)
   854  		if err := os.WriteFile(name, append(data, '\n'), 0666); err != nil {
   855  			t.Fatal(err)
   856  		}
   857  		tg.sleep()
   858  		return func() {
   859  			if err := os.WriteFile(name, old, 0666); err != nil {
   860  				t.Fatal(err)
   861  			}
   862  		}
   863  	}
   864  
   865  	// Every main package depends on the "runtime".
   866  	tg.tempFile("d1/src/p1/p1.go", `package main; func main(){}`)
   867  	tg.setenv("GOPATH", tg.path("d1"))
   868  	// Pass -i flag to rebuild everything outdated.
   869  	tg.run("install", "-i", "p1")
   870  	tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, before any changes")
   871  
   872  	// Changing mtime of runtime/internal/sys/sys.go
   873  	// should have no effect: only the content matters.
   874  	// In fact this should be true even outside a release branch.
   875  	sys := tg.path("goroot/src/runtime/internal/sys/sys.go")
   876  	tg.sleep()
   877  	restore := addVar(sys, 0)
   878  	restore()
   879  	tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after updating mtime of runtime/internal/sys/sys.go")
   880  
   881  	// But changing content of any file should have an effect.
   882  	// Previously zversion.go was the only one that mattered;
   883  	// now they all matter, so keep using sys.go.
   884  	restore = addVar(sys, 1)
   885  	defer restore()
   886  	tg.wantStale("p1", "stale dependency: runtime/internal/sys", "./testgo list claims p1 is NOT stale, incorrectly, after changing sys.go")
   887  	restore()
   888  	tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after changing back to old release")
   889  	addVar(sys, 2)
   890  	tg.wantStale("p1", "stale dependency: runtime", "./testgo list claims p1 is NOT stale, incorrectly, after changing sys.go again")
   891  	tg.run("install", "-i", "p1")
   892  	tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with new release")
   893  
   894  	// Restore to "old" release.
   895  	restore()
   896  	tg.wantStale("p1", "stale dependency: runtime/internal/sys", "./testgo list claims p1 is NOT stale, incorrectly, after restoring sys.go")
   897  	tg.run("install", "-i", "p1")
   898  	tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with old release")
   899  }
   900  
   901  // cmd/go: custom import path checking should not apply to Go packages without import comment.
   902  func TestIssue10952(t *testing.T) {
   903  	testenv.MustHaveExternalNetwork(t)
   904  	testenv.MustHaveExecPath(t, "git")
   905  
   906  	tg := testgo(t)
   907  	defer tg.cleanup()
   908  	tg.parallel()
   909  	tg.tempDir("src")
   910  	tg.setenv("GOPATH", tg.path("."))
   911  	const importPath = "github.com/zombiezen/go-get-issue-10952"
   912  	tg.run("get", "-d", "-u", importPath)
   913  	repoDir := tg.path("src/" + importPath)
   914  	tg.runGit(repoDir, "remote", "set-url", "origin", "https://"+importPath+".git")
   915  	tg.run("get", "-d", "-u", importPath)
   916  }
   917  
   918  func TestIssue16471(t *testing.T) {
   919  	testenv.MustHaveExternalNetwork(t)
   920  	testenv.MustHaveExecPath(t, "git")
   921  
   922  	tg := testgo(t)
   923  	defer tg.cleanup()
   924  	tg.parallel()
   925  	tg.tempDir("src")
   926  	tg.setenv("GOPATH", tg.path("."))
   927  	tg.must(os.MkdirAll(tg.path("src/rsc.io/go-get-issue-10952"), 0755))
   928  	tg.runGit(tg.path("src/rsc.io"), "clone", "https://github.com/zombiezen/go-get-issue-10952")
   929  	tg.runFail("get", "-u", "rsc.io/go-get-issue-10952")
   930  	tg.grepStderr("rsc.io/go-get-issue-10952 is a custom import path for https://github.com/rsc/go-get-issue-10952, but .* is checked out from https://github.com/zombiezen/go-get-issue-10952", "did not detect updated import path")
   931  }
   932  
   933  // Test git clone URL that uses SCP-like syntax and custom import path checking.
   934  func TestIssue11457(t *testing.T) {
   935  	testenv.MustHaveExternalNetwork(t)
   936  	testenv.MustHaveExecPath(t, "git")
   937  
   938  	tg := testgo(t)
   939  	defer tg.cleanup()
   940  	tg.parallel()
   941  	tg.tempDir("src")
   942  	tg.setenv("GOPATH", tg.path("."))
   943  	const importPath = "rsc.io/go-get-issue-11457"
   944  	tg.run("get", "-d", "-u", importPath)
   945  	repoDir := tg.path("src/" + importPath)
   946  	tg.runGit(repoDir, "remote", "set-url", "origin", "git@github.com:rsc/go-get-issue-11457")
   947  
   948  	// At this time, custom import path checking compares remotes verbatim (rather than
   949  	// just the host and path, skipping scheme and user), so we expect go get -u to fail.
   950  	// However, the goal of this test is to verify that gitRemoteRepo correctly parsed
   951  	// the SCP-like syntax, and we expect it to appear in the error message.
   952  	tg.runFail("get", "-d", "-u", importPath)
   953  	want := " is checked out from ssh://git@github.com/rsc/go-get-issue-11457"
   954  	if !strings.HasSuffix(strings.TrimSpace(tg.getStderr()), want) {
   955  		t.Error("expected clone URL to appear in stderr")
   956  	}
   957  }
   958  
   959  func TestGetGitDefaultBranch(t *testing.T) {
   960  	testenv.MustHaveExternalNetwork(t)
   961  	testenv.MustHaveExecPath(t, "git")
   962  
   963  	tg := testgo(t)
   964  	defer tg.cleanup()
   965  	tg.parallel()
   966  	tg.tempDir("src")
   967  	tg.setenv("GOPATH", tg.path("."))
   968  
   969  	// This repo has two branches, master and another-branch.
   970  	// The another-branch is the default that you get from 'git clone'.
   971  	// The go get command variants should not override this.
   972  	const importPath = "github.com/rsc/go-get-default-branch"
   973  
   974  	tg.run("get", "-d", importPath)
   975  	repoDir := tg.path("src/" + importPath)
   976  	tg.runGit(repoDir, "branch", "--contains", "HEAD")
   977  	tg.grepStdout(`\* another-branch`, "not on correct default branch")
   978  
   979  	tg.run("get", "-d", "-u", importPath)
   980  	tg.runGit(repoDir, "branch", "--contains", "HEAD")
   981  	tg.grepStdout(`\* another-branch`, "not on correct default branch")
   982  }
   983  
   984  // Security issue. Don't disable. See golang.org/issue/22125.
   985  func TestAccidentalGitCheckout(t *testing.T) {
   986  	testenv.MustHaveExternalNetwork(t)
   987  	testenv.MustHaveExecPath(t, "git")
   988  	testenv.MustHaveExecPath(t, "svn")
   989  
   990  	tg := testgo(t)
   991  	defer tg.cleanup()
   992  	tg.parallel()
   993  	tg.tempDir("src")
   994  
   995  	tg.setenv("GOPATH", tg.path("."))
   996  
   997  	tg.runFail("get", "-u", "vcs-test.golang.org/go/test1-svn-git")
   998  	tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason")
   999  
  1000  	if _, err := os.Stat(tg.path("SrC")); err == nil {
  1001  		// This case only triggers on a case-insensitive file system.
  1002  		tg.runFail("get", "-u", "vcs-test.golang.org/go/test2-svn-git/test2main")
  1003  		tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason")
  1004  	}
  1005  }
  1006  
  1007  func TestPackageMainTestCompilerFlags(t *testing.T) {
  1008  	tg := testgo(t)
  1009  	defer tg.cleanup()
  1010  	tg.parallel()
  1011  	tg.makeTempdir()
  1012  	tg.setenv("GOPATH", tg.path("."))
  1013  	tg.tempFile("src/p1/p1.go", "package main\n")
  1014  	tg.tempFile("src/p1/p1_test.go", "package main\nimport \"testing\"\nfunc Test(t *testing.T){}\n")
  1015  	tg.run("test", "-c", "-n", "p1")
  1016  	tg.grepBothNot(`([\\/]compile|gccgo).* (-p main|-fgo-pkgpath=main).*p1\.go`, "should not have run compile -p main p1.go")
  1017  	tg.grepStderr(`([\\/]compile|gccgo).* (-p p1|-fgo-pkgpath=p1).*p1\.go`, "should have run compile -p p1 p1.go")
  1018  }
  1019  
  1020  // Issue 4104.
  1021  func TestGoTestWithPackageListedMultipleTimes(t *testing.T) {
  1022  	tooSlow(t)
  1023  	tg := testgo(t)
  1024  	defer tg.cleanup()
  1025  	tg.parallel()
  1026  	tg.run("test", "errors", "errors", "errors", "errors", "errors")
  1027  	if strings.Contains(strings.TrimSpace(tg.getStdout()), "\n") {
  1028  		t.Error("go test errors errors errors errors errors tested the same package multiple times")
  1029  	}
  1030  }
  1031  
  1032  func TestGoListHasAConsistentOrder(t *testing.T) {
  1033  	tooSlow(t)
  1034  	tg := testgo(t)
  1035  	defer tg.cleanup()
  1036  	tg.parallel()
  1037  	tg.run("list", "std")
  1038  	first := tg.getStdout()
  1039  	tg.run("list", "std")
  1040  	if first != tg.getStdout() {
  1041  		t.Error("go list std ordering is inconsistent")
  1042  	}
  1043  }
  1044  
  1045  func TestGoListStdDoesNotIncludeCommands(t *testing.T) {
  1046  	tooSlow(t)
  1047  	tg := testgo(t)
  1048  	defer tg.cleanup()
  1049  	tg.parallel()
  1050  	tg.run("list", "std")
  1051  	tg.grepStdoutNot("cmd/", "go list std shows commands")
  1052  }
  1053  
  1054  func TestGoListCmdOnlyShowsCommands(t *testing.T) {
  1055  	skipIfGccgo(t, "gccgo does not have GOROOT")
  1056  	tooSlow(t)
  1057  	tg := testgo(t)
  1058  	defer tg.cleanup()
  1059  	tg.parallel()
  1060  	tg.run("list", "cmd")
  1061  	out := strings.TrimSpace(tg.getStdout())
  1062  	for _, line := range strings.Split(out, "\n") {
  1063  		if !strings.Contains(line, "cmd/") {
  1064  			t.Error("go list cmd shows non-commands")
  1065  			break
  1066  		}
  1067  	}
  1068  }
  1069  
  1070  func TestGoListDeps(t *testing.T) {
  1071  	tg := testgo(t)
  1072  	defer tg.cleanup()
  1073  	tg.parallel()
  1074  	tg.tempDir("src/p1/p2/p3/p4")
  1075  	tg.setenv("GOPATH", tg.path("."))
  1076  	tg.tempFile("src/p1/p.go", "package p1\nimport _ \"p1/p2\"\n")
  1077  	tg.tempFile("src/p1/p2/p.go", "package p2\nimport _ \"p1/p2/p3\"\n")
  1078  	tg.tempFile("src/p1/p2/p3/p.go", "package p3\nimport _ \"p1/p2/p3/p4\"\n")
  1079  	tg.tempFile("src/p1/p2/p3/p4/p.go", "package p4\n")
  1080  	tg.run("list", "-f", "{{.Deps}}", "p1")
  1081  	tg.grepStdout("p1/p2/p3/p4", "Deps(p1) does not mention p4")
  1082  
  1083  	tg.run("list", "-deps", "p1")
  1084  	tg.grepStdout("p1/p2/p3/p4", "-deps p1 does not mention p4")
  1085  
  1086  	if runtime.Compiler != "gccgo" {
  1087  		// Check the list is in dependency order.
  1088  		tg.run("list", "-deps", "math")
  1089  		want := "internal/cpu\nunsafe\nmath/bits\nmath\n"
  1090  		out := tg.stdout.String()
  1091  		if !strings.Contains(out, "internal/cpu") {
  1092  			// Some systems don't use internal/cpu.
  1093  			want = "unsafe\nmath/bits\nmath\n"
  1094  		}
  1095  		if tg.stdout.String() != want {
  1096  			t.Fatalf("list -deps math: wrong order\nhave %q\nwant %q", tg.stdout.String(), want)
  1097  		}
  1098  	}
  1099  }
  1100  
  1101  func TestGoListTest(t *testing.T) {
  1102  	skipIfGccgo(t, "gccgo does not have standard packages")
  1103  	tg := testgo(t)
  1104  	defer tg.cleanup()
  1105  	tg.parallel()
  1106  	tg.makeTempdir()
  1107  	tg.setenv("GOCACHE", tg.tempdir)
  1108  
  1109  	tg.run("list", "-test", "-deps", "sort")
  1110  	tg.grepStdout(`^sort.test$`, "missing test main")
  1111  	tg.grepStdout(`^sort$`, "missing real sort")
  1112  	tg.grepStdout(`^sort \[sort.test\]$`, "missing test copy of sort")
  1113  	tg.grepStdout(`^testing \[sort.test\]$`, "missing test copy of testing")
  1114  	tg.grepStdoutNot(`^testing$`, "unexpected real copy of testing")
  1115  
  1116  	tg.run("list", "-test", "sort")
  1117  	tg.grepStdout(`^sort.test$`, "missing test main")
  1118  	tg.grepStdout(`^sort$`, "missing real sort")
  1119  	tg.grepStdout(`^sort \[sort.test\]$`, "unexpected test copy of sort")
  1120  	tg.grepStdoutNot(`^testing \[sort.test\]$`, "unexpected test copy of testing")
  1121  	tg.grepStdoutNot(`^testing$`, "unexpected real copy of testing")
  1122  
  1123  	tg.run("list", "-test", "cmd/dist", "cmd/doc")
  1124  	tg.grepStdout(`^cmd/dist$`, "missing cmd/dist")
  1125  	tg.grepStdout(`^cmd/doc$`, "missing cmd/doc")
  1126  	tg.grepStdout(`^cmd/doc\.test$`, "missing cmd/doc test")
  1127  	tg.grepStdoutNot(`^cmd/dist\.test$`, "unexpected cmd/dist test")
  1128  	tg.grepStdoutNot(`^testing`, "unexpected testing")
  1129  
  1130  	tg.run("list", "-test", "runtime/cgo")
  1131  	tg.grepStdout(`^runtime/cgo$`, "missing runtime/cgo")
  1132  
  1133  	tg.run("list", "-deps", "-f", "{{if .DepOnly}}{{.ImportPath}}{{end}}", "sort")
  1134  	tg.grepStdout(`^internal/reflectlite$`, "missing internal/reflectlite")
  1135  	tg.grepStdoutNot(`^sort`, "unexpected sort")
  1136  }
  1137  
  1138  func TestGoListCompiledCgo(t *testing.T) {
  1139  	tooSlow(t)
  1140  	tg := testgo(t)
  1141  	defer tg.cleanup()
  1142  	tg.parallel()
  1143  	tg.makeTempdir()
  1144  	tg.setenv("GOCACHE", tg.tempdir)
  1145  
  1146  	tg.run("list", "-f", `{{join .CgoFiles "\n"}}`, "net")
  1147  	if tg.stdout.String() == "" {
  1148  		t.Skip("net does not use cgo")
  1149  	}
  1150  	if strings.Contains(tg.stdout.String(), tg.tempdir) {
  1151  		t.Fatalf(".CgoFiles unexpectedly mentioned cache %s", tg.tempdir)
  1152  	}
  1153  	tg.run("list", "-compiled", "-f", `{{.Dir}}{{"\n"}}{{join .CompiledGoFiles "\n"}}`, "net")
  1154  	if !strings.Contains(tg.stdout.String(), tg.tempdir) {
  1155  		t.Fatalf(".CompiledGoFiles with -compiled did not mention cache %s", tg.tempdir)
  1156  	}
  1157  	dir := ""
  1158  	for _, file := range strings.Split(tg.stdout.String(), "\n") {
  1159  		if file == "" {
  1160  			continue
  1161  		}
  1162  		if dir == "" {
  1163  			dir = file
  1164  			continue
  1165  		}
  1166  		if !strings.Contains(file, "/") && !strings.Contains(file, `\`) {
  1167  			file = filepath.Join(dir, file)
  1168  		}
  1169  		if _, err := os.Stat(file); err != nil {
  1170  			t.Fatalf("cannot find .CompiledGoFiles result %s: %v", file, err)
  1171  		}
  1172  	}
  1173  }
  1174  
  1175  func TestGoListExport(t *testing.T) {
  1176  	skipIfGccgo(t, "gccgo does not have standard packages")
  1177  	tg := testgo(t)
  1178  	defer tg.cleanup()
  1179  	tg.parallel()
  1180  	tg.makeTempdir()
  1181  	tg.setenv("GOCACHE", tg.tempdir)
  1182  
  1183  	tg.run("list", "-f", "{{.Export}}", "strings")
  1184  	if tg.stdout.String() != "" {
  1185  		t.Fatalf(".Export without -export unexpectedly set")
  1186  	}
  1187  	tg.run("list", "-export", "-f", "{{.Export}}", "strings")
  1188  	file := strings.TrimSpace(tg.stdout.String())
  1189  	if file == "" {
  1190  		t.Fatalf(".Export with -export was empty")
  1191  	}
  1192  	if _, err := os.Stat(file); err != nil {
  1193  		t.Fatalf("cannot find .Export result %s: %v", file, err)
  1194  	}
  1195  
  1196  	tg.run("list", "-export", "-f", "{{.BuildID}}", "strings")
  1197  	buildID := strings.TrimSpace(tg.stdout.String())
  1198  	if buildID == "" {
  1199  		t.Fatalf(".BuildID with -export was empty")
  1200  	}
  1201  
  1202  	tg.run("tool", "buildid", file)
  1203  	toolBuildID := strings.TrimSpace(tg.stdout.String())
  1204  	if buildID != toolBuildID {
  1205  		t.Fatalf(".BuildID with -export %q disagrees with 'go tool buildid' %q", buildID, toolBuildID)
  1206  	}
  1207  }
  1208  
  1209  // Issue 4096. Validate the output of unsuccessful go install foo/quxx.
  1210  func TestUnsuccessfulGoInstallShouldMentionMissingPackage(t *testing.T) {
  1211  	tg := testgo(t)
  1212  	defer tg.cleanup()
  1213  	tg.parallel()
  1214  	tg.runFail("install", "foo/quxx")
  1215  	if tg.grepCountBoth(`cannot find package "foo/quxx" in any of`) != 1 {
  1216  		t.Error(`go install foo/quxx expected error: .*cannot find package "foo/quxx" in any of`)
  1217  	}
  1218  }
  1219  
  1220  func TestGOROOTSearchFailureReporting(t *testing.T) {
  1221  	tg := testgo(t)
  1222  	defer tg.cleanup()
  1223  	tg.parallel()
  1224  	tg.runFail("install", "foo/quxx")
  1225  	if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("foo", "quxx"))+` \(from \$GOROOT\)$`) != 1 {
  1226  		t.Error(`go install foo/quxx expected error: .*foo/quxx (from $GOROOT)`)
  1227  	}
  1228  }
  1229  
  1230  func TestMultipleGOPATHEntriesReportedSeparately(t *testing.T) {
  1231  	tg := testgo(t)
  1232  	defer tg.cleanup()
  1233  	tg.parallel()
  1234  	sep := string(filepath.ListSeparator)
  1235  	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
  1236  	tg.runFail("install", "foo/quxx")
  1237  	if tg.grepCountBoth(`testdata[/\\].[/\\]src[/\\]foo[/\\]quxx`) != 2 {
  1238  		t.Error(`go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)\n.*testdata/b/src/foo/quxx`)
  1239  	}
  1240  }
  1241  
  1242  // Test (from $GOPATH) annotation is reported for the first GOPATH entry,
  1243  func TestMentionGOPATHInFirstGOPATHEntry(t *testing.T) {
  1244  	tg := testgo(t)
  1245  	defer tg.cleanup()
  1246  	tg.parallel()
  1247  	sep := string(filepath.ListSeparator)
  1248  	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
  1249  	tg.runFail("install", "foo/quxx")
  1250  	if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("testdata", "a", "src", "foo", "quxx"))+` \(from \$GOPATH\)$`) != 1 {
  1251  		t.Error(`go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)`)
  1252  	}
  1253  }
  1254  
  1255  // but not on the second.
  1256  func TestMentionGOPATHNotOnSecondEntry(t *testing.T) {
  1257  	tg := testgo(t)
  1258  	defer tg.cleanup()
  1259  	tg.parallel()
  1260  	sep := string(filepath.ListSeparator)
  1261  	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
  1262  	tg.runFail("install", "foo/quxx")
  1263  	if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("testdata", "b", "src", "foo", "quxx"))+`$`) != 1 {
  1264  		t.Error(`go install foo/quxx expected error: .*testdata/b/src/foo/quxx`)
  1265  	}
  1266  }
  1267  
  1268  func homeEnvName() string {
  1269  	switch runtime.GOOS {
  1270  	case "windows":
  1271  		return "USERPROFILE"
  1272  	case "plan9":
  1273  		return "home"
  1274  	default:
  1275  		return "HOME"
  1276  	}
  1277  }
  1278  
  1279  func tempEnvName() string {
  1280  	switch runtime.GOOS {
  1281  	case "windows":
  1282  		return "TMP"
  1283  	case "plan9":
  1284  		return "TMPDIR" // actually plan 9 doesn't have one at all but this is fine
  1285  	default:
  1286  		return "TMPDIR"
  1287  	}
  1288  }
  1289  
  1290  func TestDefaultGOPATH(t *testing.T) {
  1291  	tg := testgo(t)
  1292  	defer tg.cleanup()
  1293  	tg.parallel()
  1294  	tg.tempDir("home/go")
  1295  	tg.setenv(homeEnvName(), tg.path("home"))
  1296  
  1297  	tg.run("env", "GOPATH")
  1298  	tg.grepStdout(regexp.QuoteMeta(tg.path("home/go")), "want GOPATH=$HOME/go")
  1299  
  1300  	tg.setenv("GOROOT", tg.path("home/go"))
  1301  	tg.run("env", "GOPATH")
  1302  	tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go")
  1303  
  1304  	tg.setenv("GOROOT", tg.path("home/go")+"/")
  1305  	tg.run("env", "GOPATH")
  1306  	tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go/")
  1307  }
  1308  
  1309  func TestDefaultGOPATHGet(t *testing.T) {
  1310  	testenv.MustHaveExternalNetwork(t)
  1311  	testenv.MustHaveExecPath(t, "git")
  1312  
  1313  	tg := testgo(t)
  1314  	defer tg.cleanup()
  1315  	tg.parallel()
  1316  	tg.setenv("GOPATH", "")
  1317  	tg.tempDir("home")
  1318  	tg.setenv(homeEnvName(), tg.path("home"))
  1319  
  1320  	// warn for creating directory
  1321  	tg.run("get", "-v", "github.com/golang/example/hello")
  1322  	tg.grepStderr("created GOPATH="+regexp.QuoteMeta(tg.path("home/go"))+"; see 'go help gopath'", "did not create GOPATH")
  1323  
  1324  	// no warning if directory already exists
  1325  	tg.must(robustio.RemoveAll(tg.path("home/go")))
  1326  	tg.tempDir("home/go")
  1327  	tg.run("get", "github.com/golang/example/hello")
  1328  	tg.grepStderrNot(".", "expected no output on standard error")
  1329  
  1330  	// error if $HOME/go is a file
  1331  	tg.must(robustio.RemoveAll(tg.path("home/go")))
  1332  	tg.tempFile("home/go", "")
  1333  	tg.runFail("get", "github.com/golang/example/hello")
  1334  	tg.grepStderr(`mkdir .*[/\\]go: .*(not a directory|cannot find the path)`, "expected error because $HOME/go is a file")
  1335  }
  1336  
  1337  func TestDefaultGOPATHPrintedSearchList(t *testing.T) {
  1338  	tg := testgo(t)
  1339  	defer tg.cleanup()
  1340  	tg.parallel()
  1341  	tg.setenv("GOPATH", "")
  1342  	tg.tempDir("home")
  1343  	tg.setenv(homeEnvName(), tg.path("home"))
  1344  
  1345  	tg.runFail("install", "github.com/golang/example/hello")
  1346  	tg.grepStderr(regexp.QuoteMeta(tg.path("home/go/src/github.com/golang/example/hello"))+`.*from \$GOPATH`, "expected default GOPATH")
  1347  }
  1348  
  1349  func TestLdflagsArgumentsWithSpacesIssue3941(t *testing.T) {
  1350  	skipIfGccgo(t, "gccgo does not support -ldflags -X")
  1351  	tooSlow(t)
  1352  	tg := testgo(t)
  1353  	defer tg.cleanup()
  1354  	tg.parallel()
  1355  	tg.tempFile("main.go", `package main
  1356  		var extern string
  1357  		func main() {
  1358  			println(extern)
  1359  		}`)
  1360  	tg.run("run", "-ldflags", `-X "main.extern=hello world"`, tg.path("main.go"))
  1361  	tg.grepStderr("^hello world", `ldflags -X "main.extern=hello world"' failed`)
  1362  }
  1363  
  1364  func TestLdFlagsLongArgumentsIssue42295(t *testing.T) {
  1365  	// Test the extremely long command line arguments that contain '\n' characters
  1366  	// get encoded and passed correctly.
  1367  	skipIfGccgo(t, "gccgo does not support -ldflags -X")
  1368  	tooSlow(t)
  1369  	tg := testgo(t)
  1370  	defer tg.cleanup()
  1371  	tg.parallel()
  1372  	tg.tempFile("main.go", `package main
  1373  		var extern string
  1374  		func main() {
  1375  			print(extern)
  1376  		}`)
  1377  	testStr := "test test test test test \n\\ "
  1378  	var buf bytes.Buffer
  1379  	for buf.Len() < work.ArgLengthForResponseFile+1 {
  1380  		buf.WriteString(testStr)
  1381  	}
  1382  	tg.run("run", "-ldflags", fmt.Sprintf(`-X "main.extern=%s"`, buf.String()), tg.path("main.go"))
  1383  	if tg.stderr.String() != buf.String() {
  1384  		t.Errorf("strings differ")
  1385  	}
  1386  }
  1387  
  1388  func TestGoTestDashCDashOControlsBinaryLocation(t *testing.T) {
  1389  	skipIfGccgo(t, "gccgo has no standard packages")
  1390  	tooSlow(t)
  1391  	tg := testgo(t)
  1392  	defer tg.cleanup()
  1393  	tg.parallel()
  1394  	tg.makeTempdir()
  1395  	tg.run("test", "-c", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
  1396  	tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -c -o myerrors.test did not create myerrors.test")
  1397  }
  1398  
  1399  func TestGoTestDashOWritesBinary(t *testing.T) {
  1400  	skipIfGccgo(t, "gccgo has no standard packages")
  1401  	tooSlow(t)
  1402  	tg := testgo(t)
  1403  	defer tg.cleanup()
  1404  	tg.parallel()
  1405  	tg.makeTempdir()
  1406  	tg.run("test", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
  1407  	tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -o myerrors.test did not create myerrors.test")
  1408  }
  1409  
  1410  func TestGoTestDashIDashOWritesBinary(t *testing.T) {
  1411  	skipIfGccgo(t, "gccgo has no standard packages")
  1412  	tooSlow(t)
  1413  	tg := testgo(t)
  1414  	defer tg.cleanup()
  1415  	tg.parallel()
  1416  	tg.makeTempdir()
  1417  
  1418  	// don't let test -i overwrite runtime
  1419  	tg.wantNotStale("runtime", "", "must be non-stale before test -i")
  1420  
  1421  	tg.run("test", "-v", "-i", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
  1422  	tg.grepBothNot("PASS|FAIL", "test should not have run")
  1423  	tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -o myerrors.test did not create myerrors.test")
  1424  }
  1425  
  1426  // Issue 4515.
  1427  func TestInstallWithTags(t *testing.T) {
  1428  	tooSlow(t)
  1429  	tg := testgo(t)
  1430  	defer tg.cleanup()
  1431  	tg.parallel()
  1432  	tg.tempDir("bin")
  1433  	tg.tempFile("src/example/a/main.go", `package main
  1434  		func main() {}`)
  1435  	tg.tempFile("src/example/b/main.go", `// +build mytag
  1436  
  1437  		package main
  1438  		func main() {}`)
  1439  	tg.setenv("GOPATH", tg.path("."))
  1440  	tg.run("install", "-tags", "mytag", "example/a", "example/b")
  1441  	tg.wantExecutable(tg.path("bin/a"+exeSuffix), "go install example/a example/b did not install binaries")
  1442  	tg.wantExecutable(tg.path("bin/b"+exeSuffix), "go install example/a example/b did not install binaries")
  1443  	tg.must(os.Remove(tg.path("bin/a" + exeSuffix)))
  1444  	tg.must(os.Remove(tg.path("bin/b" + exeSuffix)))
  1445  	tg.run("install", "-tags", "mytag", "example/...")
  1446  	tg.wantExecutable(tg.path("bin/a"+exeSuffix), "go install example/... did not install binaries")
  1447  	tg.wantExecutable(tg.path("bin/b"+exeSuffix), "go install example/... did not install binaries")
  1448  	tg.run("list", "-tags", "mytag", "example/b...")
  1449  	if strings.TrimSpace(tg.getStdout()) != "example/b" {
  1450  		t.Error("go list example/b did not find example/b")
  1451  	}
  1452  }
  1453  
  1454  // Issue 17451, 17662.
  1455  func TestSymlinkWarning(t *testing.T) {
  1456  	tg := testgo(t)
  1457  	defer tg.cleanup()
  1458  	tg.parallel()
  1459  	tg.makeTempdir()
  1460  	tg.setenv("GOPATH", tg.path("."))
  1461  
  1462  	tg.tempDir("src/example/xx")
  1463  	tg.tempDir("yy/zz")
  1464  	tg.tempFile("yy/zz/zz.go", "package zz\n")
  1465  	if err := os.Symlink(tg.path("yy"), tg.path("src/example/xx/yy")); err != nil {
  1466  		t.Skipf("symlink failed: %v", err)
  1467  	}
  1468  	tg.run("list", "example/xx/z...")
  1469  	tg.grepStdoutNot(".", "list should not have matched anything")
  1470  	tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages")
  1471  	tg.grepStderrNot("symlink", "list should not have reported symlink")
  1472  
  1473  	tg.run("list", "example/xx/...")
  1474  	tg.grepStdoutNot(".", "list should not have matched anything")
  1475  	tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages")
  1476  	tg.grepStderr("ignoring symlink", "list should have reported symlink")
  1477  }
  1478  
  1479  func TestCgoShowsFullPathNames(t *testing.T) {
  1480  	if !canCgo {
  1481  		t.Skip("skipping because cgo not enabled")
  1482  	}
  1483  
  1484  	tg := testgo(t)
  1485  	defer tg.cleanup()
  1486  	tg.parallel()
  1487  	tg.tempFile("src/x/y/dirname/foo.go", `
  1488  		package foo
  1489  		import "C"
  1490  		func f() {`)
  1491  	tg.setenv("GOPATH", tg.path("."))
  1492  	tg.runFail("build", "x/y/dirname")
  1493  	tg.grepBoth("x/y/dirname", "error did not use full path")
  1494  }
  1495  
  1496  func TestCgoHandlesWlORIGIN(t *testing.T) {
  1497  	tooSlow(t)
  1498  	if !canCgo {
  1499  		t.Skip("skipping because cgo not enabled")
  1500  	}
  1501  
  1502  	tg := testgo(t)
  1503  	defer tg.cleanup()
  1504  	tg.parallel()
  1505  	tg.tempFile("src/origin/origin.go", `package origin
  1506  		// #cgo !darwin LDFLAGS: -Wl,-rpath,$ORIGIN
  1507  		// void f(void) {}
  1508  		import "C"
  1509  		func f() { C.f() }`)
  1510  	tg.setenv("GOPATH", tg.path("."))
  1511  	tg.run("build", "origin")
  1512  }
  1513  
  1514  func TestCgoPkgConfig(t *testing.T) {
  1515  	tooSlow(t)
  1516  	if !canCgo {
  1517  		t.Skip("skipping because cgo not enabled")
  1518  	}
  1519  	tg := testgo(t)
  1520  	defer tg.cleanup()
  1521  	tg.parallel()
  1522  
  1523  	tg.run("env", "PKG_CONFIG")
  1524  	pkgConfig := strings.TrimSpace(tg.getStdout())
  1525  	testenv.MustHaveExecPath(t, pkgConfig)
  1526  	if out, err := exec.Command(pkgConfig, "--atleast-pkgconfig-version", "0.24").CombinedOutput(); err != nil {
  1527  		t.Skipf("%s --atleast-pkgconfig-version 0.24: %v\n%s", pkgConfig, err, out)
  1528  	}
  1529  
  1530  	// OpenBSD's pkg-config is strict about whitespace and only
  1531  	// supports backslash-escaped whitespace. It does not support
  1532  	// quotes, which the normal freedesktop.org pkg-config does
  1533  	// support. See https://man.openbsd.org/pkg-config.1
  1534  	tg.tempFile("foo.pc", `
  1535  Name: foo
  1536  Description: The foo library
  1537  Version: 1.0.0
  1538  Cflags: -Dhello=10 -Dworld=+32 -DDEFINED_FROM_PKG_CONFIG=hello\ world
  1539  `)
  1540  	tg.tempFile("foo.go", `package main
  1541  
  1542  /*
  1543  #cgo pkg-config: foo
  1544  int value() {
  1545  	return DEFINED_FROM_PKG_CONFIG;
  1546  }
  1547  */
  1548  import "C"
  1549  import "os"
  1550  
  1551  func main() {
  1552  	if C.value() != 42 {
  1553  		println("value() =", C.value(), "wanted 42")
  1554  		os.Exit(1)
  1555  	}
  1556  }
  1557  `)
  1558  	tg.setenv("PKG_CONFIG_PATH", tg.path("."))
  1559  	tg.run("run", tg.path("foo.go"))
  1560  }
  1561  
  1562  func TestListTemplateContextFunction(t *testing.T) {
  1563  	t.Parallel()
  1564  	for _, tt := range []struct {
  1565  		v    string
  1566  		want string
  1567  	}{
  1568  		{"GOARCH", runtime.GOARCH},
  1569  		{"GOOS", runtime.GOOS},
  1570  		{"GOROOT", filepath.Clean(runtime.GOROOT())},
  1571  		{"GOPATH", os.Getenv("GOPATH")},
  1572  		{"CgoEnabled", ""},
  1573  		{"UseAllFiles", ""},
  1574  		{"Compiler", ""},
  1575  		{"BuildTags", ""},
  1576  		{"ReleaseTags", ""},
  1577  		{"InstallSuffix", ""},
  1578  	} {
  1579  		tt := tt
  1580  		t.Run(tt.v, func(t *testing.T) {
  1581  			tg := testgo(t)
  1582  			tg.parallel()
  1583  			defer tg.cleanup()
  1584  			tmpl := "{{context." + tt.v + "}}"
  1585  			tg.run("list", "-f", tmpl)
  1586  			if tt.want == "" {
  1587  				return
  1588  			}
  1589  			if got := strings.TrimSpace(tg.getStdout()); got != tt.want {
  1590  				t.Errorf("go list -f %q: got %q; want %q", tmpl, got, tt.want)
  1591  			}
  1592  		})
  1593  	}
  1594  }
  1595  
  1596  // Test that you cannot use a local import in a package
  1597  // accessed by a non-local import (found in a GOPATH/GOROOT).
  1598  // See golang.org/issue/17475.
  1599  func TestImportLocal(t *testing.T) {
  1600  	tooSlow(t)
  1601  
  1602  	tg := testgo(t)
  1603  	tg.parallel()
  1604  	defer tg.cleanup()
  1605  
  1606  	tg.tempFile("src/dir/x/x.go", `package x
  1607  		var X int
  1608  	`)
  1609  	tg.setenv("GOPATH", tg.path("."))
  1610  	tg.run("build", "dir/x")
  1611  
  1612  	// Ordinary import should work.
  1613  	tg.tempFile("src/dir/p0/p.go", `package p0
  1614  		import "dir/x"
  1615  		var _ = x.X
  1616  	`)
  1617  	tg.run("build", "dir/p0")
  1618  
  1619  	// Relative import should not.
  1620  	tg.tempFile("src/dir/p1/p.go", `package p1
  1621  		import "../x"
  1622  		var _ = x.X
  1623  	`)
  1624  	tg.runFail("build", "dir/p1")
  1625  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1626  
  1627  	// ... even in a test.
  1628  	tg.tempFile("src/dir/p2/p.go", `package p2
  1629  	`)
  1630  	tg.tempFile("src/dir/p2/p_test.go", `package p2
  1631  		import "../x"
  1632  		import "testing"
  1633  		var _ = x.X
  1634  		func TestFoo(t *testing.T) {}
  1635  	`)
  1636  	tg.run("build", "dir/p2")
  1637  	tg.runFail("test", "dir/p2")
  1638  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1639  
  1640  	// ... even in an xtest.
  1641  	tg.tempFile("src/dir/p2/p_test.go", `package p2_test
  1642  		import "../x"
  1643  		import "testing"
  1644  		var _ = x.X
  1645  		func TestFoo(t *testing.T) {}
  1646  	`)
  1647  	tg.run("build", "dir/p2")
  1648  	tg.runFail("test", "dir/p2")
  1649  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1650  
  1651  	// Relative import starting with ./ should not work either.
  1652  	tg.tempFile("src/dir/d.go", `package dir
  1653  		import "./x"
  1654  		var _ = x.X
  1655  	`)
  1656  	tg.runFail("build", "dir")
  1657  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1658  
  1659  	// ... even in a test.
  1660  	tg.tempFile("src/dir/d.go", `package dir
  1661  	`)
  1662  	tg.tempFile("src/dir/d_test.go", `package dir
  1663  		import "./x"
  1664  		import "testing"
  1665  		var _ = x.X
  1666  		func TestFoo(t *testing.T) {}
  1667  	`)
  1668  	tg.run("build", "dir")
  1669  	tg.runFail("test", "dir")
  1670  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1671  
  1672  	// ... even in an xtest.
  1673  	tg.tempFile("src/dir/d_test.go", `package dir_test
  1674  		import "./x"
  1675  		import "testing"
  1676  		var _ = x.X
  1677  		func TestFoo(t *testing.T) {}
  1678  	`)
  1679  	tg.run("build", "dir")
  1680  	tg.runFail("test", "dir")
  1681  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1682  
  1683  	// Relative import plain ".." should not work.
  1684  	tg.tempFile("src/dir/x/y/y.go", `package dir
  1685  		import ".."
  1686  		var _ = x.X
  1687  	`)
  1688  	tg.runFail("build", "dir/x/y")
  1689  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1690  
  1691  	// ... even in a test.
  1692  	tg.tempFile("src/dir/x/y/y.go", `package y
  1693  	`)
  1694  	tg.tempFile("src/dir/x/y/y_test.go", `package y
  1695  		import ".."
  1696  		import "testing"
  1697  		var _ = x.X
  1698  		func TestFoo(t *testing.T) {}
  1699  	`)
  1700  	tg.run("build", "dir/x/y")
  1701  	tg.runFail("test", "dir/x/y")
  1702  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1703  
  1704  	// ... even in an x test.
  1705  	tg.tempFile("src/dir/x/y/y_test.go", `package y_test
  1706  		import ".."
  1707  		import "testing"
  1708  		var _ = x.X
  1709  		func TestFoo(t *testing.T) {}
  1710  	`)
  1711  	tg.run("build", "dir/x/y")
  1712  	tg.runFail("test", "dir/x/y")
  1713  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1714  
  1715  	// Relative import "." should not work.
  1716  	tg.tempFile("src/dir/x/xx.go", `package x
  1717  		import "."
  1718  		var _ = x.X
  1719  	`)
  1720  	tg.runFail("build", "dir/x")
  1721  	tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
  1722  
  1723  	// ... even in a test.
  1724  	tg.tempFile("src/dir/x/xx.go", `package x
  1725  	`)
  1726  	tg.tempFile("src/dir/x/xx_test.go", `package x
  1727  		import "."
  1728  		import "testing"
  1729  		var _ = x.X
  1730  		func TestFoo(t *testing.T) {}
  1731  	`)
  1732  	tg.run("build", "dir/x")
  1733  	tg.runFail("test", "dir/x")
  1734  	tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
  1735  
  1736  	// ... even in an xtest.
  1737  	tg.tempFile("src/dir/x/xx.go", `package x
  1738  	`)
  1739  	tg.tempFile("src/dir/x/xx_test.go", `package x_test
  1740  		import "."
  1741  		import "testing"
  1742  		var _ = x.X
  1743  		func TestFoo(t *testing.T) {}
  1744  	`)
  1745  	tg.run("build", "dir/x")
  1746  	tg.runFail("test", "dir/x")
  1747  	tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
  1748  }
  1749  
  1750  func TestGoInstallPkgdir(t *testing.T) {
  1751  	skipIfGccgo(t, "gccgo has no standard packages")
  1752  	tooSlow(t)
  1753  
  1754  	tg := testgo(t)
  1755  	tg.parallel()
  1756  	defer tg.cleanup()
  1757  	tg.makeTempdir()
  1758  	pkg := tg.path(".")
  1759  	tg.run("install", "-pkgdir", pkg, "sync")
  1760  	tg.mustExist(filepath.Join(pkg, "sync.a"))
  1761  	tg.mustNotExist(filepath.Join(pkg, "sync/atomic.a"))
  1762  	tg.run("install", "-i", "-pkgdir", pkg, "sync")
  1763  	tg.mustExist(filepath.Join(pkg, "sync.a"))
  1764  	tg.mustExist(filepath.Join(pkg, "sync/atomic.a"))
  1765  }
  1766  
  1767  // For issue 14337.
  1768  func TestParallelTest(t *testing.T) {
  1769  	tooSlow(t)
  1770  	tg := testgo(t)
  1771  	tg.parallel()
  1772  	defer tg.cleanup()
  1773  	tg.makeTempdir()
  1774  	const testSrc = `package package_test
  1775  		import (
  1776  			"testing"
  1777  		)
  1778  		func TestTest(t *testing.T) {
  1779  		}`
  1780  	tg.tempFile("src/p1/p1_test.go", strings.Replace(testSrc, "package_test", "p1_test", 1))
  1781  	tg.tempFile("src/p2/p2_test.go", strings.Replace(testSrc, "package_test", "p2_test", 1))
  1782  	tg.tempFile("src/p3/p3_test.go", strings.Replace(testSrc, "package_test", "p3_test", 1))
  1783  	tg.tempFile("src/p4/p4_test.go", strings.Replace(testSrc, "package_test", "p4_test", 1))
  1784  	tg.setenv("GOPATH", tg.path("."))
  1785  	tg.run("test", "-p=4", "p1", "p2", "p3", "p4")
  1786  }
  1787  
  1788  func TestBinaryOnlyPackages(t *testing.T) {
  1789  	tooSlow(t)
  1790  
  1791  	tg := testgo(t)
  1792  	defer tg.cleanup()
  1793  	tg.parallel()
  1794  	tg.makeTempdir()
  1795  	tg.setenv("GOPATH", tg.path("."))
  1796  
  1797  	tg.tempFile("src/p1/p1.go", `//go:binary-only-package
  1798  
  1799  		package p1
  1800  	`)
  1801  	tg.wantStale("p1", "binary-only packages are no longer supported", "p1 is binary-only, and this message should always be printed")
  1802  	tg.runFail("install", "p1")
  1803  	tg.grepStderr("binary-only packages are no longer supported", "did not report attempt to compile binary-only package")
  1804  
  1805  	tg.tempFile("src/p1/p1.go", `
  1806  		package p1
  1807  		import "fmt"
  1808  		func F(b bool) { fmt.Printf("hello from p1\n"); if b { F(false) } }
  1809  	`)
  1810  	tg.run("install", "p1")
  1811  	os.Remove(tg.path("src/p1/p1.go"))
  1812  	tg.mustNotExist(tg.path("src/p1/p1.go"))
  1813  
  1814  	tg.tempFile("src/p2/p2.go", `//go:binary-only-packages-are-not-great
  1815  
  1816  		package p2
  1817  		import "p1"
  1818  		func F() { p1.F(true) }
  1819  	`)
  1820  	tg.runFail("install", "p2")
  1821  	tg.grepStderr("no Go files", "did not complain about missing sources")
  1822  
  1823  	tg.tempFile("src/p1/missing.go", `//go:binary-only-package
  1824  
  1825  		package p1
  1826  		import _ "fmt"
  1827  		func G()
  1828  	`)
  1829  	tg.wantStale("p1", "binary-only package", "should NOT want to rebuild p1 (first)")
  1830  	tg.runFail("install", "p2")
  1831  	tg.grepStderr("p1: binary-only packages are no longer supported", "did not report error for binary-only p1")
  1832  
  1833  	tg.run("list", "-deps", "-f", "{{.ImportPath}}: {{.BinaryOnly}}", "p2")
  1834  	tg.grepStdout("p1: true", "p1 not listed as BinaryOnly")
  1835  	tg.grepStdout("p2: false", "p2 listed as BinaryOnly")
  1836  }
  1837  
  1838  // Issue 16050.
  1839  func TestAlwaysLinkSysoFiles(t *testing.T) {
  1840  	tg := testgo(t)
  1841  	defer tg.cleanup()
  1842  	tg.parallel()
  1843  	tg.tempDir("src/syso")
  1844  	tg.tempFile("src/syso/a.syso", ``)
  1845  	tg.tempFile("src/syso/b.go", `package syso`)
  1846  	tg.setenv("GOPATH", tg.path("."))
  1847  
  1848  	// We should see the .syso file regardless of the setting of
  1849  	// CGO_ENABLED.
  1850  
  1851  	tg.setenv("CGO_ENABLED", "1")
  1852  	tg.run("list", "-f", "{{.SysoFiles}}", "syso")
  1853  	tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=1")
  1854  
  1855  	tg.setenv("CGO_ENABLED", "0")
  1856  	tg.run("list", "-f", "{{.SysoFiles}}", "syso")
  1857  	tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=0")
  1858  }
  1859  
  1860  // Issue 16120.
  1861  func TestGenerateUsesBuildContext(t *testing.T) {
  1862  	if runtime.GOOS == "windows" {
  1863  		t.Skip("this test won't run under Windows")
  1864  	}
  1865  
  1866  	tg := testgo(t)
  1867  	defer tg.cleanup()
  1868  	tg.parallel()
  1869  	tg.tempDir("src/gen")
  1870  	tg.tempFile("src/gen/gen.go", "package gen\n//go:generate echo $GOOS $GOARCH\n")
  1871  	tg.setenv("GOPATH", tg.path("."))
  1872  
  1873  	tg.setenv("GOOS", "linux")
  1874  	tg.setenv("GOARCH", "amd64")
  1875  	tg.run("generate", "gen")
  1876  	tg.grepStdout("linux amd64", "unexpected GOOS/GOARCH combination")
  1877  
  1878  	tg.setenv("GOOS", "darwin")
  1879  	tg.setenv("GOARCH", "arm64")
  1880  	tg.run("generate", "gen")
  1881  	tg.grepStdout("darwin arm64", "unexpected GOOS/GOARCH combination")
  1882  }
  1883  
  1884  func TestGoEnv(t *testing.T) {
  1885  	tg := testgo(t)
  1886  	tg.parallel()
  1887  	defer tg.cleanup()
  1888  	tg.setenv("GOOS", "freebsd") // to avoid invalid pair errors
  1889  	tg.setenv("GOARCH", "arm")
  1890  	tg.run("env", "GOARCH")
  1891  	tg.grepStdout("^arm$", "GOARCH not honored")
  1892  
  1893  	tg.run("env", "GCCGO")
  1894  	tg.grepStdout(".", "GCCGO unexpectedly empty")
  1895  
  1896  	tg.run("env", "CGO_CFLAGS")
  1897  	tg.grepStdout(".", "default CGO_CFLAGS unexpectedly empty")
  1898  
  1899  	tg.setenv("CGO_CFLAGS", "-foobar")
  1900  	tg.run("env", "CGO_CFLAGS")
  1901  	tg.grepStdout("^-foobar$", "CGO_CFLAGS not honored")
  1902  
  1903  	tg.setenv("CC", "gcc -fmust -fgo -ffaster")
  1904  	tg.run("env", "CC")
  1905  	tg.grepStdout("gcc", "CC not found")
  1906  	tg.run("env", "GOGCCFLAGS")
  1907  	tg.grepStdout("-ffaster", "CC arguments not found")
  1908  
  1909  	tg.run("env", "GOVERSION")
  1910  	envVersion := strings.TrimSpace(tg.stdout.String())
  1911  
  1912  	tg.run("version")
  1913  	cmdVersion := strings.TrimSpace(tg.stdout.String())
  1914  
  1915  	// If 'go version' is "go version <version> <goos>/<goarch>", then
  1916  	// 'go env GOVERSION' is just "<version>".
  1917  	if cmdVersion == envVersion || !strings.Contains(cmdVersion, envVersion) {
  1918  		t.Fatalf("'go env GOVERSION' %q should be a shorter substring of 'go version' %q", envVersion, cmdVersion)
  1919  	}
  1920  }
  1921  
  1922  const (
  1923  	noMatchesPattern = `(?m)^ok.*\[no tests to run\]`
  1924  	okPattern        = `(?m)^ok`
  1925  )
  1926  
  1927  // Issue 18044.
  1928  func TestLdBindNow(t *testing.T) {
  1929  	tg := testgo(t)
  1930  	defer tg.cleanup()
  1931  	tg.parallel()
  1932  	tg.setenv("LD_BIND_NOW", "1")
  1933  	tg.run("help")
  1934  }
  1935  
  1936  // Issue 18225.
  1937  // This is really a cmd/asm issue but this is a convenient place to test it.
  1938  func TestConcurrentAsm(t *testing.T) {
  1939  	skipIfGccgo(t, "gccgo does not use cmd/asm")
  1940  	tg := testgo(t)
  1941  	defer tg.cleanup()
  1942  	tg.parallel()
  1943  	asm := `DATA ·constants<>+0x0(SB)/8,$0
  1944  GLOBL ·constants<>(SB),8,$8
  1945  `
  1946  	tg.tempFile("go/src/p/a.s", asm)
  1947  	tg.tempFile("go/src/p/b.s", asm)
  1948  	tg.tempFile("go/src/p/p.go", `package p`)
  1949  	tg.setenv("GOPATH", tg.path("go"))
  1950  	tg.run("build", "p")
  1951  }
  1952  
  1953  // Issue 18975.
  1954  func TestFFLAGS(t *testing.T) {
  1955  	if !canCgo {
  1956  		t.Skip("skipping because cgo not enabled")
  1957  	}
  1958  
  1959  	tg := testgo(t)
  1960  	defer tg.cleanup()
  1961  	tg.parallel()
  1962  
  1963  	tg.tempFile("p/src/p/main.go", `package main
  1964  		// #cgo FFLAGS: -no-such-fortran-flag
  1965  		import "C"
  1966  		func main() {}
  1967  	`)
  1968  	tg.tempFile("p/src/p/a.f", `! comment`)
  1969  	tg.setenv("GOPATH", tg.path("p"))
  1970  
  1971  	// This should normally fail because we are passing an unknown flag,
  1972  	// but issue #19080 points to Fortran compilers that succeed anyhow.
  1973  	// To work either way we call doRun directly rather than run or runFail.
  1974  	tg.doRun([]string{"build", "-x", "p"})
  1975  
  1976  	tg.grepStderr("no-such-fortran-flag", `missing expected "-no-such-fortran-flag"`)
  1977  }
  1978  
  1979  // Issue 19198.
  1980  // This is really a cmd/link issue but this is a convenient place to test it.
  1981  func TestDuplicateGlobalAsmSymbols(t *testing.T) {
  1982  	skipIfGccgo(t, "gccgo does not use cmd/asm")
  1983  	tooSlow(t)
  1984  	if runtime.GOARCH != "386" && runtime.GOARCH != "amd64" {
  1985  		t.Skipf("skipping test on %s", runtime.GOARCH)
  1986  	}
  1987  	if !canCgo {
  1988  		t.Skip("skipping because cgo not enabled")
  1989  	}
  1990  
  1991  	tg := testgo(t)
  1992  	defer tg.cleanup()
  1993  	tg.parallel()
  1994  
  1995  	asm := `
  1996  #include "textflag.h"
  1997  
  1998  DATA sym<>+0x0(SB)/8,$0
  1999  GLOBL sym<>(SB),(NOPTR+RODATA),$8
  2000  
  2001  TEXT ·Data(SB),NOSPLIT,$0
  2002  	MOVB sym<>(SB), AX
  2003  	MOVB AX, ret+0(FP)
  2004  	RET
  2005  `
  2006  	tg.tempFile("go/src/a/a.s", asm)
  2007  	tg.tempFile("go/src/a/a.go", `package a; func Data() uint8`)
  2008  	tg.tempFile("go/src/b/b.s", asm)
  2009  	tg.tempFile("go/src/b/b.go", `package b; func Data() uint8`)
  2010  	tg.tempFile("go/src/p/p.go", `
  2011  package main
  2012  import "a"
  2013  import "b"
  2014  import "C"
  2015  func main() {
  2016  	_ = a.Data() + b.Data()
  2017  }
  2018  `)
  2019  	tg.setenv("GOPATH", tg.path("go"))
  2020  	exe := tg.path("p.exe")
  2021  	tg.creatingTemp(exe)
  2022  	tg.run("build", "-o", exe, "p")
  2023  }
  2024  
  2025  func copyFile(src, dst string, perm fs.FileMode) error {
  2026  	sf, err := os.Open(src)
  2027  	if err != nil {
  2028  		return err
  2029  	}
  2030  	defer sf.Close()
  2031  
  2032  	df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
  2033  	if err != nil {
  2034  		return err
  2035  	}
  2036  
  2037  	_, err = io.Copy(df, sf)
  2038  	err2 := df.Close()
  2039  	if err != nil {
  2040  		return err
  2041  	}
  2042  	return err2
  2043  }
  2044  
  2045  func TestNeedVersion(t *testing.T) {
  2046  	skipIfGccgo(t, "gccgo does not use cmd/compile")
  2047  	tg := testgo(t)
  2048  	defer tg.cleanup()
  2049  	tg.parallel()
  2050  	tg.tempFile("goversion.go", `package main; func main() {}`)
  2051  	path := tg.path("goversion.go")
  2052  	tg.setenv("TESTGO_VERSION", "go1.testgo")
  2053  	tg.runFail("run", path)
  2054  	tg.grepStderr("compile", "does not match go tool version")
  2055  }
  2056  
  2057  func TestBuildmodePIE(t *testing.T) {
  2058  	if testing.Short() && testenv.Builder() == "" {
  2059  		t.Skipf("skipping in -short mode on non-builder")
  2060  	}
  2061  
  2062  	platform := fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)
  2063  	switch platform {
  2064  	case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/riscv64", "linux/s390x",
  2065  		"android/amd64", "android/arm", "android/arm64", "android/386",
  2066  		"freebsd/amd64",
  2067  		"windows/386", "windows/amd64", "windows/arm":
  2068  	case "darwin/amd64":
  2069  	default:
  2070  		t.Skipf("skipping test because buildmode=pie is not supported on %s", platform)
  2071  	}
  2072  	t.Run("non-cgo", func(t *testing.T) {
  2073  		testBuildmodePIE(t, false, true)
  2074  	})
  2075  	if canCgo {
  2076  		switch runtime.GOOS {
  2077  		case "darwin", "freebsd", "linux", "windows":
  2078  			t.Run("cgo", func(t *testing.T) {
  2079  				testBuildmodePIE(t, true, true)
  2080  			})
  2081  		}
  2082  	}
  2083  }
  2084  
  2085  func TestWindowsDefaultBuildmodIsPIE(t *testing.T) {
  2086  	if testing.Short() && testenv.Builder() == "" {
  2087  		t.Skipf("skipping in -short mode on non-builder")
  2088  	}
  2089  
  2090  	if runtime.GOOS != "windows" {
  2091  		t.Skip("skipping windows only test")
  2092  	}
  2093  
  2094  	t.Run("non-cgo", func(t *testing.T) {
  2095  		testBuildmodePIE(t, false, false)
  2096  	})
  2097  	if canCgo {
  2098  		t.Run("cgo", func(t *testing.T) {
  2099  			testBuildmodePIE(t, true, false)
  2100  		})
  2101  	}
  2102  }
  2103  
  2104  func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) {
  2105  	tg := testgo(t)
  2106  	defer tg.cleanup()
  2107  	tg.parallel()
  2108  
  2109  	var s string
  2110  	if useCgo {
  2111  		s = `import "C";`
  2112  	}
  2113  	tg.tempFile("main.go", fmt.Sprintf(`package main;%s func main() { print("hello") }`, s))
  2114  	src := tg.path("main.go")
  2115  	obj := tg.path("main.exe")
  2116  	args := []string{"build"}
  2117  	if setBuildmodeToPIE {
  2118  		args = append(args, "-buildmode=pie")
  2119  	}
  2120  	args = append(args, "-o", obj, src)
  2121  	tg.run(args...)
  2122  
  2123  	switch runtime.GOOS {
  2124  	case "linux", "android", "freebsd":
  2125  		f, err := elf.Open(obj)
  2126  		if err != nil {
  2127  			t.Fatal(err)
  2128  		}
  2129  		defer f.Close()
  2130  		if f.Type != elf.ET_DYN {
  2131  			t.Errorf("PIE type must be ET_DYN, but %s", f.Type)
  2132  		}
  2133  	case "darwin":
  2134  		f, err := macho.Open(obj)
  2135  		if err != nil {
  2136  			t.Fatal(err)
  2137  		}
  2138  		defer f.Close()
  2139  		if f.Flags&macho.FlagDyldLink == 0 {
  2140  			t.Error("PIE must have DyldLink flag, but not")
  2141  		}
  2142  		if f.Flags&macho.FlagPIE == 0 {
  2143  			t.Error("PIE must have PIE flag, but not")
  2144  		}
  2145  	case "windows":
  2146  		f, err := pe.Open(obj)
  2147  		if err != nil {
  2148  			t.Fatal(err)
  2149  		}
  2150  		defer f.Close()
  2151  		if f.Section(".reloc") == nil {
  2152  			t.Error(".reloc section is not present")
  2153  		}
  2154  		if (f.FileHeader.Characteristics & pe.IMAGE_FILE_RELOCS_STRIPPED) != 0 {
  2155  			t.Error("IMAGE_FILE_RELOCS_STRIPPED flag is set")
  2156  		}
  2157  		var dc uint16
  2158  		switch oh := f.OptionalHeader.(type) {
  2159  		case *pe.OptionalHeader32:
  2160  			dc = oh.DllCharacteristics
  2161  		case *pe.OptionalHeader64:
  2162  			dc = oh.DllCharacteristics
  2163  			if (dc & pe.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) == 0 {
  2164  				t.Error("IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA flag is not set")
  2165  			}
  2166  		default:
  2167  			t.Fatalf("unexpected optional header type of %T", f.OptionalHeader)
  2168  		}
  2169  		if (dc & pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 {
  2170  			t.Error("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag is not set")
  2171  		}
  2172  		if useCgo {
  2173  			// Test that only one symbol is exported (#40795).
  2174  			// PIE binaries don´t require .edata section but unfortunately
  2175  			// binutils doesn´t generate a .reloc section unless there is
  2176  			// at least one symbol exported.
  2177  			// See https://sourceware.org/bugzilla/show_bug.cgi?id=19011
  2178  			section := f.Section(".edata")
  2179  			if section == nil {
  2180  				t.Skip(".edata section is not present")
  2181  			}
  2182  			// TODO: deduplicate this struct from cmd/link/internal/ld/pe.go
  2183  			type IMAGE_EXPORT_DIRECTORY struct {
  2184  				_                 [2]uint32
  2185  				_                 [2]uint16
  2186  				_                 [2]uint32
  2187  				NumberOfFunctions uint32
  2188  				NumberOfNames     uint32
  2189  				_                 [3]uint32
  2190  			}
  2191  			var e IMAGE_EXPORT_DIRECTORY
  2192  			if err := binary.Read(section.Open(), binary.LittleEndian, &e); err != nil {
  2193  				t.Fatalf("binary.Read failed: %v", err)
  2194  			}
  2195  
  2196  			// Only _cgo_dummy_export should be exported
  2197  			if e.NumberOfFunctions != 1 {
  2198  				t.Fatalf("got %d exported functions; want 1", e.NumberOfFunctions)
  2199  			}
  2200  			if e.NumberOfNames != 1 {
  2201  				t.Fatalf("got %d exported names; want 1", e.NumberOfNames)
  2202  			}
  2203  		}
  2204  	default:
  2205  		panic("unreachable")
  2206  	}
  2207  
  2208  	out, err := exec.Command(obj).CombinedOutput()
  2209  	if err != nil {
  2210  		t.Fatal(err)
  2211  	}
  2212  
  2213  	if string(out) != "hello" {
  2214  		t.Errorf("got %q; want %q", out, "hello")
  2215  	}
  2216  }
  2217  
  2218  func TestUpxCompression(t *testing.T) {
  2219  	if runtime.GOOS != "linux" ||
  2220  		(runtime.GOARCH != "amd64" && runtime.GOARCH != "386") {
  2221  		t.Skipf("skipping upx test on %s/%s", runtime.GOOS, runtime.GOARCH)
  2222  	}
  2223  
  2224  	testenv.MustHaveExecPath(t, "upx")
  2225  	out, err := exec.Command("upx", "--version").CombinedOutput()
  2226  	if err != nil {
  2227  		t.Fatalf("upx --version failed: %v", err)
  2228  	}
  2229  
  2230  	// upx --version prints `upx <version>` in the first line of output:
  2231  	//   upx 3.94
  2232  	//   [...]
  2233  	re := regexp.MustCompile(`([[:digit:]]+)\.([[:digit:]]+)`)
  2234  	upxVersion := re.FindStringSubmatch(string(out))
  2235  	if len(upxVersion) != 3 {
  2236  		t.Fatalf("bad upx version string: %s", upxVersion)
  2237  	}
  2238  
  2239  	major, err1 := strconv.Atoi(upxVersion[1])
  2240  	minor, err2 := strconv.Atoi(upxVersion[2])
  2241  	if err1 != nil || err2 != nil {
  2242  		t.Fatalf("bad upx version string: %s", upxVersion[0])
  2243  	}
  2244  
  2245  	// Anything below 3.94 is known not to work with go binaries
  2246  	if (major < 3) || (major == 3 && minor < 94) {
  2247  		t.Skipf("skipping because upx version %v.%v is too old", major, minor)
  2248  	}
  2249  
  2250  	tg := testgo(t)
  2251  	defer tg.cleanup()
  2252  	tg.parallel()
  2253  
  2254  	tg.tempFile("main.go", `package main; import "fmt"; func main() { fmt.Print("hello upx") }`)
  2255  	src := tg.path("main.go")
  2256  	obj := tg.path("main")
  2257  	tg.run("build", "-o", obj, src)
  2258  
  2259  	out, err = exec.Command("upx", obj).CombinedOutput()
  2260  	if err != nil {
  2261  		t.Logf("executing upx\n%s\n", out)
  2262  		t.Fatalf("upx failed with %v", err)
  2263  	}
  2264  
  2265  	out, err = exec.Command(obj).CombinedOutput()
  2266  	if err != nil {
  2267  		t.Logf("%s", out)
  2268  		t.Fatalf("running compressed go binary failed with error %s", err)
  2269  	}
  2270  	if string(out) != "hello upx" {
  2271  		t.Fatalf("bad output from compressed go binary:\ngot %q; want %q", out, "hello upx")
  2272  	}
  2273  }
  2274  
  2275  func TestCacheListStale(t *testing.T) {
  2276  	tooSlow(t)
  2277  	if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") {
  2278  		t.Skip("GODEBUG gocacheverify")
  2279  	}
  2280  	tg := testgo(t)
  2281  	defer tg.cleanup()
  2282  	tg.parallel()
  2283  	tg.makeTempdir()
  2284  	tg.setenv("GOCACHE", tg.path("cache"))
  2285  	tg.tempFile("gopath/src/p/p.go", "package p; import _ \"q\"; func F(){}\n")
  2286  	tg.tempFile("gopath/src/q/q.go", "package q; func F(){}\n")
  2287  	tg.tempFile("gopath/src/m/m.go", "package main; import _ \"q\"; func main(){}\n")
  2288  
  2289  	tg.setenv("GOPATH", tg.path("gopath"))
  2290  	tg.run("install", "p", "m")
  2291  	tg.run("list", "-f={{.ImportPath}} {{.Stale}}", "m", "q", "p")
  2292  	tg.grepStdout("^m false", "m should not be stale")
  2293  	tg.grepStdout("^q true", "q should be stale")
  2294  	tg.grepStdout("^p false", "p should not be stale")
  2295  }
  2296  
  2297  func TestCacheCoverage(t *testing.T) {
  2298  	tooSlow(t)
  2299  
  2300  	if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") {
  2301  		t.Skip("GODEBUG gocacheverify")
  2302  	}
  2303  
  2304  	tg := testgo(t)
  2305  	defer tg.cleanup()
  2306  	tg.parallel()
  2307  	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
  2308  	tg.makeTempdir()
  2309  
  2310  	tg.setenv("GOCACHE", tg.path("c1"))
  2311  	tg.run("test", "-cover", "-short", "strings")
  2312  	tg.run("test", "-cover", "-short", "math", "strings")
  2313  }
  2314  
  2315  func TestIssue22588(t *testing.T) {
  2316  	// Don't get confused by stderr coming from tools.
  2317  	tg := testgo(t)
  2318  	defer tg.cleanup()
  2319  	tg.parallel()
  2320  
  2321  	if _, err := os.Stat("/usr/bin/time"); err != nil {
  2322  		t.Skip(err)
  2323  	}
  2324  
  2325  	tg.run("list", "-f={{.Stale}}", "runtime")
  2326  	tg.run("list", "-toolexec=/usr/bin/time", "-f={{.Stale}}", "runtime")
  2327  	tg.grepStdout("false", "incorrectly reported runtime as stale")
  2328  }
  2329  
  2330  func TestIssue22531(t *testing.T) {
  2331  	tooSlow(t)
  2332  	if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") {
  2333  		t.Skip("GODEBUG gocacheverify")
  2334  	}
  2335  	tg := testgo(t)
  2336  	defer tg.cleanup()
  2337  	tg.parallel()
  2338  	tg.makeTempdir()
  2339  	tg.setenv("GOPATH", tg.tempdir)
  2340  	tg.setenv("GOCACHE", tg.path("cache"))
  2341  	tg.tempFile("src/m/main.go", "package main /* c1 */; func main() {}\n")
  2342  	tg.run("install", "-x", "m")
  2343  	tg.run("list", "-f", "{{.Stale}}", "m")
  2344  	tg.grepStdout("false", "reported m as stale after install")
  2345  	tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix))
  2346  
  2347  	// The link action ID did not include the full main build ID,
  2348  	// even though the full main build ID is written into the
  2349  	// eventual binary. That caused the following install to
  2350  	// be a no-op, thinking the gofmt binary was up-to-date,
  2351  	// even though .Stale could see it was not.
  2352  	tg.tempFile("src/m/main.go", "package main /* c2 */; func main() {}\n")
  2353  	tg.run("install", "-x", "m")
  2354  	tg.run("list", "-f", "{{.Stale}}", "m")
  2355  	tg.grepStdout("false", "reported m as stale after reinstall")
  2356  	tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix))
  2357  }
  2358  
  2359  func TestIssue22596(t *testing.T) {
  2360  	tooSlow(t)
  2361  	if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") {
  2362  		t.Skip("GODEBUG gocacheverify")
  2363  	}
  2364  	tg := testgo(t)
  2365  	defer tg.cleanup()
  2366  	tg.parallel()
  2367  	tg.makeTempdir()
  2368  	tg.setenv("GOCACHE", tg.path("cache"))
  2369  	tg.tempFile("gopath1/src/p/p.go", "package p; func F(){}\n")
  2370  	tg.tempFile("gopath2/src/p/p.go", "package p; func F(){}\n")
  2371  
  2372  	tg.setenv("GOPATH", tg.path("gopath1"))
  2373  	tg.run("list", "-f={{.Target}}", "p")
  2374  	target1 := strings.TrimSpace(tg.getStdout())
  2375  	tg.run("install", "p")
  2376  	tg.wantNotStale("p", "", "p stale after install")
  2377  
  2378  	tg.setenv("GOPATH", tg.path("gopath2"))
  2379  	tg.run("list", "-f={{.Target}}", "p")
  2380  	target2 := strings.TrimSpace(tg.getStdout())
  2381  	tg.must(os.MkdirAll(filepath.Dir(target2), 0777))
  2382  	tg.must(copyFile(target1, target2, 0666))
  2383  	tg.wantStale("p", "build ID mismatch", "p not stale after copy from gopath1")
  2384  	tg.run("install", "p")
  2385  	tg.wantNotStale("p", "", "p stale after install2")
  2386  }
  2387  
  2388  func TestTestCache(t *testing.T) {
  2389  	tooSlow(t)
  2390  
  2391  	if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") {
  2392  		t.Skip("GODEBUG gocacheverify")
  2393  	}
  2394  	tg := testgo(t)
  2395  	defer tg.cleanup()
  2396  	tg.parallel()
  2397  	tg.makeTempdir()
  2398  	tg.setenv("GOPATH", tg.tempdir)
  2399  	tg.setenv("GOCACHE", tg.path("cache"))
  2400  
  2401  	// The -p=1 in the commands below just makes the -x output easier to read.
  2402  
  2403  	t.Log("\n\nINITIAL\n\n")
  2404  
  2405  	tg.tempFile("src/p1/p1.go", "package p1\nvar X =  1\n")
  2406  	tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\nvar X = 1\n")
  2407  	tg.tempFile("src/t/t1/t1_test.go", "package t\nimport \"testing\"\nfunc Test1(*testing.T) {}\n")
  2408  	tg.tempFile("src/t/t2/t2_test.go", "package t\nimport _ \"p1\"\nimport \"testing\"\nfunc Test2(*testing.T) {}\n")
  2409  	tg.tempFile("src/t/t3/t3_test.go", "package t\nimport \"p1\"\nimport \"testing\"\nfunc Test3(t *testing.T) {t.Log(p1.X)}\n")
  2410  	tg.tempFile("src/t/t4/t4_test.go", "package t\nimport \"p2\"\nimport \"testing\"\nfunc Test4(t *testing.T) {t.Log(p2.X)}")
  2411  	tg.run("test", "-x", "-v", "-short", "t/...")
  2412  
  2413  	t.Log("\n\nREPEAT\n\n")
  2414  
  2415  	tg.run("test", "-x", "-v", "-short", "t/...")
  2416  	tg.grepStdout(`ok  \tt/t1\t\(cached\)`, "did not cache t1")
  2417  	tg.grepStdout(`ok  \tt/t2\t\(cached\)`, "did not cache t2")
  2418  	tg.grepStdout(`ok  \tt/t3\t\(cached\)`, "did not cache t3")
  2419  	tg.grepStdout(`ok  \tt/t4\t\(cached\)`, "did not cache t4")
  2420  	tg.grepStderrNot(`[\\/](compile|gccgo) `, "incorrectly ran compiler")
  2421  	tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker")
  2422  	tg.grepStderrNot(`p[0-9]\.test`, "incorrectly ran test")
  2423  
  2424  	t.Log("\n\nCOMMENT\n\n")
  2425  
  2426  	// Changing the program text without affecting the compiled package
  2427  	// should result in the package being rebuilt but nothing more.
  2428  	tg.tempFile("src/p1/p1.go", "package p1\nvar X = 01\n")
  2429  	tg.run("test", "-p=1", "-x", "-v", "-short", "t/...")
  2430  	tg.grepStdout(`ok  \tt/t1\t\(cached\)`, "did not cache t1")
  2431  	tg.grepStdout(`ok  \tt/t2\t\(cached\)`, "did not cache t2")
  2432  	tg.grepStdout(`ok  \tt/t3\t\(cached\)`, "did not cache t3")
  2433  	tg.grepStdout(`ok  \tt/t4\t\(cached\)`, "did not cache t4")
  2434  	tg.grepStderrNot(`([\\/](compile|gccgo) ).*t[0-9]_test\.go`, "incorrectly ran compiler")
  2435  	tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker")
  2436  	tg.grepStderrNot(`t[0-9]\.test.*test\.short`, "incorrectly ran test")
  2437  
  2438  	t.Log("\n\nCHANGE\n\n")
  2439  
  2440  	// Changing the actual package should have limited effects.
  2441  	tg.tempFile("src/p1/p1.go", "package p1\nvar X = 02\n")
  2442  	tg.run("test", "-p=1", "-x", "-v", "-short", "t/...")
  2443  
  2444  	// p2 should have been rebuilt.
  2445  	tg.grepStderr(`([\\/]compile|gccgo).*p2.go`, "did not recompile p2")
  2446  
  2447  	// t1 does not import anything, should not have been rebuilt.
  2448  	tg.grepStderrNot(`([\\/]compile|gccgo).*t1_test.go`, "incorrectly recompiled t1")
  2449  	tg.grepStderrNot(`([\\/]link|gccgo).*t1_test`, "incorrectly relinked t1_test")
  2450  	tg.grepStdout(`ok  \tt/t1\t\(cached\)`, "did not cache t/t1")
  2451  
  2452  	// t2 imports p1 and must be rebuilt and relinked,
  2453  	// but the change should not have any effect on the test binary,
  2454  	// so the test should not have been rerun.
  2455  	tg.grepStderr(`([\\/]compile|gccgo).*t2_test.go`, "did not recompile t2")
  2456  	tg.grepStderr(`([\\/]link|gccgo).*t2\.test`, "did not relink t2_test")
  2457  	// This check does not currently work with gccgo, as garbage
  2458  	// collection of unused variables is not turned on by default.
  2459  	if runtime.Compiler != "gccgo" {
  2460  		tg.grepStdout(`ok  \tt/t2\t\(cached\)`, "did not cache t/t2")
  2461  	}
  2462  
  2463  	// t3 imports p1, and changing X changes t3's test binary.
  2464  	tg.grepStderr(`([\\/]compile|gccgo).*t3_test.go`, "did not recompile t3")
  2465  	tg.grepStderr(`([\\/]link|gccgo).*t3\.test`, "did not relink t3_test")
  2466  	tg.grepStderr(`t3\.test.*-test.short`, "did not rerun t3_test")
  2467  	tg.grepStdoutNot(`ok  \tt/t3\t\(cached\)`, "reported cached t3_test result")
  2468  
  2469  	// t4 imports p2, but p2 did not change, so t4 should be relinked, not recompiled,
  2470  	// and not rerun.
  2471  	tg.grepStderrNot(`([\\/]compile|gccgo).*t4_test.go`, "incorrectly recompiled t4")
  2472  	tg.grepStderr(`([\\/]link|gccgo).*t4\.test`, "did not relink t4_test")
  2473  	// This check does not currently work with gccgo, as garbage
  2474  	// collection of unused variables is not turned on by default.
  2475  	if runtime.Compiler != "gccgo" {
  2476  		tg.grepStdout(`ok  \tt/t4\t\(cached\)`, "did not cache t/t4")
  2477  	}
  2478  }
  2479  
  2480  func TestTestSkipVetAfterFailedBuild(t *testing.T) {
  2481  	tg := testgo(t)
  2482  	defer tg.cleanup()
  2483  	tg.parallel()
  2484  
  2485  	tg.tempFile("x_test.go", `package x
  2486  		func f() {
  2487  			return 1
  2488  		}
  2489  	`)
  2490  
  2491  	tg.runFail("test", tg.path("x_test.go"))
  2492  	tg.grepStderrNot(`vet`, "vet should be skipped after the failed build")
  2493  }
  2494  
  2495  func TestTestVetRebuild(t *testing.T) {
  2496  	tooSlow(t)
  2497  	tg := testgo(t)
  2498  	defer tg.cleanup()
  2499  	tg.parallel()
  2500  
  2501  	// golang.org/issue/23701.
  2502  	// b_test imports b with augmented method from export_test.go.
  2503  	// b_test also imports a, which imports b.
  2504  	// Must not accidentally see un-augmented b propagate through a to b_test.
  2505  	tg.tempFile("src/a/a.go", `package a
  2506  		import "b"
  2507  		type Type struct{}
  2508  		func (*Type) M() b.T {return 0}
  2509  	`)
  2510  	tg.tempFile("src/b/b.go", `package b
  2511  		type T int
  2512  		type I interface {M() T}
  2513  	`)
  2514  	tg.tempFile("src/b/export_test.go", `package b
  2515  		func (*T) Method() *T { return nil }
  2516  	`)
  2517  	tg.tempFile("src/b/b_test.go", `package b_test
  2518  		import (
  2519  			"testing"
  2520  			"a"
  2521  			. "b"
  2522  		)
  2523  		func TestBroken(t *testing.T) {
  2524  			x := new(T)
  2525  			x.Method()
  2526  			_ = new(a.Type)
  2527  		}
  2528  	`)
  2529  
  2530  	tg.setenv("GOPATH", tg.path("."))
  2531  	tg.run("test", "b")
  2532  	tg.run("vet", "b")
  2533  }
  2534  
  2535  func TestInstallDeps(t *testing.T) {
  2536  	tooSlow(t)
  2537  	tg := testgo(t)
  2538  	defer tg.cleanup()
  2539  	tg.parallel()
  2540  	tg.makeTempdir()
  2541  	tg.setenv("GOPATH", tg.tempdir)
  2542  
  2543  	tg.tempFile("src/p1/p1.go", "package p1\nvar X =  1\n")
  2544  	tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\n")
  2545  	tg.tempFile("src/main1/main.go", "package main\nimport _ \"p2\"\nfunc main() {}\n")
  2546  
  2547  	tg.run("list", "-f={{.Target}}", "p1")
  2548  	p1 := strings.TrimSpace(tg.getStdout())
  2549  	tg.run("list", "-f={{.Target}}", "p2")
  2550  	p2 := strings.TrimSpace(tg.getStdout())
  2551  	tg.run("list", "-f={{.Target}}", "main1")
  2552  	main1 := strings.TrimSpace(tg.getStdout())
  2553  
  2554  	tg.run("install", "main1")
  2555  
  2556  	tg.mustExist(main1)
  2557  	tg.mustNotExist(p2)
  2558  	tg.mustNotExist(p1)
  2559  
  2560  	tg.run("install", "p2")
  2561  	tg.mustExist(p2)
  2562  	tg.mustNotExist(p1)
  2563  
  2564  	// don't let install -i overwrite runtime
  2565  	tg.wantNotStale("runtime", "", "must be non-stale before install -i")
  2566  
  2567  	tg.run("install", "-i", "main1")
  2568  	tg.mustExist(p1)
  2569  	tg.must(os.Remove(p1))
  2570  
  2571  	tg.run("install", "-i", "p2")
  2572  	tg.mustExist(p1)
  2573  }
  2574  
  2575  // Issue 22986.
  2576  func TestImportPath(t *testing.T) {
  2577  	tooSlow(t)
  2578  	tg := testgo(t)
  2579  	defer tg.cleanup()
  2580  	tg.parallel()
  2581  
  2582  	tg.tempFile("src/a/a.go", `
  2583  package main
  2584  
  2585  import (
  2586  	"log"
  2587  	p "a/p-1.0"
  2588  )
  2589  
  2590  func main() {
  2591  	if !p.V {
  2592  		log.Fatal("false")
  2593  	}
  2594  }`)
  2595  
  2596  	tg.tempFile("src/a/a_test.go", `
  2597  package main_test
  2598  
  2599  import (
  2600  	p "a/p-1.0"
  2601  	"testing"
  2602  )
  2603  
  2604  func TestV(t *testing.T) {
  2605  	if !p.V {
  2606  		t.Fatal("false")
  2607  	}
  2608  }`)
  2609  
  2610  	tg.tempFile("src/a/p-1.0/p.go", `
  2611  package p
  2612  
  2613  var V = true
  2614  
  2615  func init() {}
  2616  `)
  2617  
  2618  	tg.setenv("GOPATH", tg.path("."))
  2619  	tg.run("build", "-o", tg.path("a.exe"), "a")
  2620  	tg.run("test", "a")
  2621  }
  2622  
  2623  func TestBadCommandLines(t *testing.T) {
  2624  	tg := testgo(t)
  2625  	defer tg.cleanup()
  2626  	tg.parallel()
  2627  
  2628  	tg.tempFile("src/x/x.go", "package x\n")
  2629  	tg.setenv("GOPATH", tg.path("."))
  2630  
  2631  	tg.run("build", "x")
  2632  
  2633  	tg.tempFile("src/x/@y.go", "package x\n")
  2634  	tg.runFail("build", "x")
  2635  	tg.grepStderr("invalid input file name \"@y.go\"", "did not reject @y.go")
  2636  	tg.must(os.Remove(tg.path("src/x/@y.go")))
  2637  
  2638  	tg.tempFile("src/x/-y.go", "package x\n")
  2639  	tg.runFail("build", "x")
  2640  	tg.grepStderr("invalid input file name \"-y.go\"", "did not reject -y.go")
  2641  	tg.must(os.Remove(tg.path("src/x/-y.go")))
  2642  
  2643  	if runtime.Compiler == "gccgo" {
  2644  		tg.runFail("build", "-gccgoflags=all=@x", "x")
  2645  	} else {
  2646  		tg.runFail("build", "-gcflags=all=@x", "x")
  2647  	}
  2648  	tg.grepStderr("invalid command-line argument @x in command", "did not reject @x during exec")
  2649  
  2650  	tg.tempFile("src/@x/x.go", "package x\n")
  2651  	tg.setenv("GOPATH", tg.path("."))
  2652  	tg.runFail("build", "@x")
  2653  	tg.grepStderr("invalid input directory name \"@x\"|can only use path@version syntax with 'go get' and 'go install' in module-aware mode", "did not reject @x directory")
  2654  
  2655  	tg.tempFile("src/@x/y/y.go", "package y\n")
  2656  	tg.setenv("GOPATH", tg.path("."))
  2657  	tg.runFail("build", "@x/y")
  2658  	tg.grepStderr("invalid import path \"@x/y\"|can only use path@version syntax with 'go get' and 'go install' in module-aware mode", "did not reject @x/y import path")
  2659  
  2660  	tg.tempFile("src/-x/x.go", "package x\n")
  2661  	tg.setenv("GOPATH", tg.path("."))
  2662  	tg.runFail("build", "--", "-x")
  2663  	tg.grepStderr("invalid import path \"-x\"", "did not reject -x import path")
  2664  
  2665  	tg.tempFile("src/-x/y/y.go", "package y\n")
  2666  	tg.setenv("GOPATH", tg.path("."))
  2667  	tg.runFail("build", "--", "-x/y")
  2668  	tg.grepStderr("invalid import path \"-x/y\"", "did not reject -x/y import path")
  2669  }
  2670  
  2671  func TestTwoPkgConfigs(t *testing.T) {
  2672  	if !canCgo {
  2673  		t.Skip("no cgo")
  2674  	}
  2675  	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
  2676  		t.Skipf("no shell scripts on %s", runtime.GOOS)
  2677  	}
  2678  	tooSlow(t)
  2679  	tg := testgo(t)
  2680  	defer tg.cleanup()
  2681  	tg.parallel()
  2682  	tg.tempFile("src/x/a.go", `package x
  2683  		// #cgo pkg-config: --static a
  2684  		import "C"
  2685  	`)
  2686  	tg.tempFile("src/x/b.go", `package x
  2687  		// #cgo pkg-config: --static a
  2688  		import "C"
  2689  	`)
  2690  	tg.tempFile("pkg-config.sh", `#!/bin/sh
  2691  echo $* >>`+tg.path("pkg-config.out"))
  2692  	tg.must(os.Chmod(tg.path("pkg-config.sh"), 0755))
  2693  	tg.setenv("GOPATH", tg.path("."))
  2694  	tg.setenv("PKG_CONFIG", tg.path("pkg-config.sh"))
  2695  	tg.run("build", "x")
  2696  	out, err := os.ReadFile(tg.path("pkg-config.out"))
  2697  	tg.must(err)
  2698  	out = bytes.TrimSpace(out)
  2699  	want := "--cflags --static --static -- a a\n--libs --static --static -- a a"
  2700  	if !bytes.Equal(out, []byte(want)) {
  2701  		t.Errorf("got %q want %q", out, want)
  2702  	}
  2703  }
  2704  
  2705  func TestCgoCache(t *testing.T) {
  2706  	if !canCgo {
  2707  		t.Skip("no cgo")
  2708  	}
  2709  	tooSlow(t)
  2710  
  2711  	tg := testgo(t)
  2712  	defer tg.cleanup()
  2713  	tg.parallel()
  2714  	tg.tempFile("src/x/a.go", `package main
  2715  		// #ifndef VAL
  2716  		// #define VAL 0
  2717  		// #endif
  2718  		// int val = VAL;
  2719  		import "C"
  2720  		import "fmt"
  2721  		func main() { fmt.Println(C.val) }
  2722  	`)
  2723  	tg.setenv("GOPATH", tg.path("."))
  2724  	exe := tg.path("x.exe")
  2725  	tg.run("build", "-o", exe, "x")
  2726  	tg.setenv("CGO_LDFLAGS", "-lnosuchlibraryexists")
  2727  	tg.runFail("build", "-o", exe, "x")
  2728  	tg.grepStderr(`nosuchlibraryexists`, "did not run linker with changed CGO_LDFLAGS")
  2729  }
  2730  
  2731  // Issue 23982
  2732  func TestFilepathUnderCwdFormat(t *testing.T) {
  2733  	tg := testgo(t)
  2734  	defer tg.cleanup()
  2735  	tg.parallel()
  2736  	tg.run("test", "-x", "-cover", "log")
  2737  	tg.grepStderrNot(`\.log\.cover\.go`, "-x output should contain correctly formatted filepath under cwd")
  2738  }
  2739  
  2740  // Issue 24396.
  2741  func TestDontReportRemoveOfEmptyDir(t *testing.T) {
  2742  	tg := testgo(t)
  2743  	defer tg.cleanup()
  2744  	tg.parallel()
  2745  	tg.tempFile("src/a/a.go", `package a`)
  2746  	tg.setenv("GOPATH", tg.path("."))
  2747  	tg.run("install", "-x", "a")
  2748  	tg.run("install", "-x", "a")
  2749  	// The second install should have printed only a WORK= line,
  2750  	// nothing else.
  2751  	if bytes.Count(tg.stdout.Bytes(), []byte{'\n'})+bytes.Count(tg.stderr.Bytes(), []byte{'\n'}) > 1 {
  2752  		t.Error("unnecessary output when installing installed package")
  2753  	}
  2754  }
  2755  
  2756  // Issue 24704.
  2757  func TestLinkerTmpDirIsDeleted(t *testing.T) {
  2758  	skipIfGccgo(t, "gccgo does not use cmd/link")
  2759  	if !canCgo {
  2760  		t.Skip("skipping because cgo not enabled")
  2761  	}
  2762  	tooSlow(t)
  2763  
  2764  	tg := testgo(t)
  2765  	defer tg.cleanup()
  2766  	tg.parallel()
  2767  	tg.tempFile("a.go", `package main; import "C"; func main() {}`)
  2768  	tg.run("build", "-ldflags", "-v", "-o", os.DevNull, tg.path("a.go"))
  2769  	// Find line that has "host link:" in linker output.
  2770  	stderr := tg.getStderr()
  2771  	var hostLinkLine string
  2772  	for _, line := range strings.Split(stderr, "\n") {
  2773  		if !strings.Contains(line, "host link:") {
  2774  			continue
  2775  		}
  2776  		hostLinkLine = line
  2777  		break
  2778  	}
  2779  	if hostLinkLine == "" {
  2780  		t.Fatal(`fail to find with "host link:" string in linker output`)
  2781  	}
  2782  	// Find parameter, like "/tmp/go-link-408556474/go.o" inside of
  2783  	// "host link:" line, and extract temp directory /tmp/go-link-408556474
  2784  	// out of it.
  2785  	tmpdir := hostLinkLine
  2786  	i := strings.Index(tmpdir, `go.o"`)
  2787  	if i == -1 {
  2788  		t.Fatalf(`fail to find "go.o" in "host link:" line %q`, hostLinkLine)
  2789  	}
  2790  	tmpdir = tmpdir[:i-1]
  2791  	i = strings.LastIndex(tmpdir, `"`)
  2792  	if i == -1 {
  2793  		t.Fatalf(`fail to find " in "host link:" line %q`, hostLinkLine)
  2794  	}
  2795  	tmpdir = tmpdir[i+1:]
  2796  	// Verify that temp directory has been removed.
  2797  	_, err := os.Stat(tmpdir)
  2798  	if err == nil {
  2799  		t.Fatalf("temp directory %q has not been removed", tmpdir)
  2800  	}
  2801  	if !os.IsNotExist(err) {
  2802  		t.Fatalf("Stat(%q) returns unexpected error: %v", tmpdir, err)
  2803  	}
  2804  }
  2805  
  2806  // Issue 25093.
  2807  func TestCoverpkgTestOnly(t *testing.T) {
  2808  	skipIfGccgo(t, "gccgo has no cover tool")
  2809  	tooSlow(t)
  2810  	tg := testgo(t)
  2811  	defer tg.cleanup()
  2812  	tg.parallel()
  2813  	tg.tempFile("src/a/a.go", `package a
  2814  		func F(i int) int {
  2815  			return i*i
  2816  		}`)
  2817  	tg.tempFile("src/atest/a_test.go", `
  2818  		package a_test
  2819  		import ( "a"; "testing" )
  2820  		func TestF(t *testing.T) { a.F(2) }
  2821  	`)
  2822  	tg.setenv("GOPATH", tg.path("."))
  2823  	tg.run("test", "-coverpkg=a", "atest")
  2824  	tg.grepStderrNot("no packages being tested depend on matches", "bad match message")
  2825  	tg.grepStdout("coverage: 100", "no coverage")
  2826  }
  2827  
  2828  // Regression test for golang.org/issue/34499: version command should not crash
  2829  // when executed in a deleted directory on Linux.
  2830  func TestExecInDeletedDir(t *testing.T) {
  2831  	switch runtime.GOOS {
  2832  	case "windows", "plan9",
  2833  		"aix",                // Fails with "device busy".
  2834  		"solaris", "illumos": // Fails with "invalid argument".
  2835  		t.Skipf("%v does not support removing the current working directory", runtime.GOOS)
  2836  	}
  2837  	tg := testgo(t)
  2838  	defer tg.cleanup()
  2839  
  2840  	wd, err := os.Getwd()
  2841  	tg.check(err)
  2842  	tg.makeTempdir()
  2843  	tg.check(os.Chdir(tg.tempdir))
  2844  	defer func() { tg.check(os.Chdir(wd)) }()
  2845  
  2846  	tg.check(os.Remove(tg.tempdir))
  2847  
  2848  	// `go version` should not fail
  2849  	tg.run("version")
  2850  }
  2851  
  2852  // A missing C compiler should not force the net package to be stale.
  2853  // Issue 47215.
  2854  func TestMissingCC(t *testing.T) {
  2855  	if !canCgo {
  2856  		t.Skip("test is only meaningful on systems with cgo")
  2857  	}
  2858  	cc := os.Getenv("CC")
  2859  	if cc == "" {
  2860  		cc = "gcc"
  2861  	}
  2862  	if filepath.IsAbs(cc) {
  2863  		t.Skipf(`"CC" (%s) is an absolute path`, cc)
  2864  	}
  2865  	_, err := exec.LookPath(cc)
  2866  	if err != nil {
  2867  		t.Skipf(`"CC" (%s) not on PATH`, cc)
  2868  	}
  2869  
  2870  	tg := testgo(t)
  2871  	defer tg.cleanup()
  2872  	netStale, _ := tg.isStale("net")
  2873  	if netStale {
  2874  		t.Skip(`skipping test because "net" package is currently stale`)
  2875  	}
  2876  
  2877  	tg.setenv("PATH", "") // No C compiler on PATH.
  2878  	netStale, _ = tg.isStale("net")
  2879  	if netStale {
  2880  		t.Error(`clearing "PATH" causes "net" to be stale`)
  2881  	}
  2882  }
  2883  

View as plain text