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

View as plain text