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

View as plain text