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  // Issue 16050 and 21884.
  1678  func TestLinkSysoFiles(t *testing.T) {
  1679  	if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
  1680  		t.Skip("not linux/amd64")
  1681  	}
  1682  
  1683  	tg := testgo(t)
  1684  	defer tg.cleanup()
  1685  	tg.parallel()
  1686  	tg.tempDir("src/syso")
  1687  	tg.tempFile("src/syso/a.syso", ``)
  1688  	tg.tempFile("src/syso/b.go", `package syso`)
  1689  	tg.setenv("GOPATH", tg.path("."))
  1690  
  1691  	// We should see the .syso file regardless of the setting of
  1692  	// CGO_ENABLED.
  1693  
  1694  	tg.setenv("CGO_ENABLED", "1")
  1695  	tg.run("list", "-f", "{{.SysoFiles}}", "syso")
  1696  	tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=1")
  1697  
  1698  	tg.setenv("CGO_ENABLED", "0")
  1699  	tg.run("list", "-f", "{{.SysoFiles}}", "syso")
  1700  	tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=0")
  1701  
  1702  	tg.setenv("CGO_ENABLED", "1")
  1703  	tg.run("list", "-msan", "-f", "{{.SysoFiles}}", "syso")
  1704  	tg.grepStdoutNot("a.syso", "unexpected syso file with -msan")
  1705  }
  1706  
  1707  // Issue 16120.
  1708  func TestGenerateUsesBuildContext(t *testing.T) {
  1709  	if runtime.GOOS == "windows" {
  1710  		t.Skip("this test won't run under Windows")
  1711  	}
  1712  
  1713  	tg := testgo(t)
  1714  	defer tg.cleanup()
  1715  	tg.parallel()
  1716  	tg.tempDir("src/gen")
  1717  	tg.tempFile("src/gen/gen.go", "package gen\n//go:generate echo $GOOS $GOARCH\n")
  1718  	tg.setenv("GOPATH", tg.path("."))
  1719  
  1720  	tg.setenv("GOOS", "linux")
  1721  	tg.setenv("GOARCH", "amd64")
  1722  	tg.run("generate", "gen")
  1723  	tg.grepStdout("linux amd64", "unexpected GOOS/GOARCH combination")
  1724  
  1725  	tg.setenv("GOOS", "darwin")
  1726  	tg.setenv("GOARCH", "arm64")
  1727  	tg.run("generate", "gen")
  1728  	tg.grepStdout("darwin arm64", "unexpected GOOS/GOARCH combination")
  1729  }
  1730  
  1731  func TestGoEnv(t *testing.T) {
  1732  	tg := testgo(t)
  1733  	tg.parallel()
  1734  	defer tg.cleanup()
  1735  	tg.setenv("GOOS", "freebsd") // to avoid invalid pair errors
  1736  	tg.setenv("GOARCH", "arm")
  1737  	tg.run("env", "GOARCH")
  1738  	tg.grepStdout("^arm$", "GOARCH not honored")
  1739  
  1740  	tg.run("env", "GCCGO")
  1741  	tg.grepStdout(".", "GCCGO unexpectedly empty")
  1742  
  1743  	tg.run("env", "CGO_CFLAGS")
  1744  	tg.grepStdout(".", "default CGO_CFLAGS unexpectedly empty")
  1745  
  1746  	tg.setenv("CGO_CFLAGS", "-foobar")
  1747  	tg.run("env", "CGO_CFLAGS")
  1748  	tg.grepStdout("^-foobar$", "CGO_CFLAGS not honored")
  1749  
  1750  	tg.setenv("CC", "gcc -fmust -fgo -ffaster")
  1751  	tg.run("env", "CC")
  1752  	tg.grepStdout("gcc", "CC not found")
  1753  	tg.run("env", "GOGCCFLAGS")
  1754  	tg.grepStdout("-ffaster", "CC arguments not found")
  1755  
  1756  	tg.run("env", "GOVERSION")
  1757  	envVersion := strings.TrimSpace(tg.stdout.String())
  1758  
  1759  	tg.run("version")
  1760  	cmdVersion := strings.TrimSpace(tg.stdout.String())
  1761  
  1762  	// If 'go version' is "go version <version> <goos>/<goarch>", then
  1763  	// 'go env GOVERSION' is just "<version>".
  1764  	if cmdVersion == envVersion || !strings.Contains(cmdVersion, envVersion) {
  1765  		t.Fatalf("'go env GOVERSION' %q should be a shorter substring of 'go version' %q", envVersion, cmdVersion)
  1766  	}
  1767  }
  1768  
  1769  const (
  1770  	noMatchesPattern = `(?m)^ok.*\[no tests to run\]`
  1771  	okPattern        = `(?m)^ok`
  1772  )
  1773  
  1774  // Issue 18044.
  1775  func TestLdBindNow(t *testing.T) {
  1776  	tg := testgo(t)
  1777  	defer tg.cleanup()
  1778  	tg.parallel()
  1779  	tg.setenv("LD_BIND_NOW", "1")
  1780  	tg.run("help")
  1781  }
  1782  
  1783  // Issue 18225.
  1784  // This is really a cmd/asm issue but this is a convenient place to test it.
  1785  func TestConcurrentAsm(t *testing.T) {
  1786  	skipIfGccgo(t, "gccgo does not use cmd/asm")
  1787  	tg := testgo(t)
  1788  	defer tg.cleanup()
  1789  	tg.parallel()
  1790  	asm := `DATA ·constants<>+0x0(SB)/8,$0
  1791  GLOBL ·constants<>(SB),8,$8
  1792  `
  1793  	tg.tempFile("go/src/p/a.s", asm)
  1794  	tg.tempFile("go/src/p/b.s", asm)
  1795  	tg.tempFile("go/src/p/p.go", `package p`)
  1796  	tg.setenv("GOPATH", tg.path("go"))
  1797  	tg.run("build", "p")
  1798  }
  1799  
  1800  // Issue 18975.
  1801  func TestFFLAGS(t *testing.T) {
  1802  	testenv.MustHaveCGO(t)
  1803  
  1804  	tg := testgo(t)
  1805  	defer tg.cleanup()
  1806  	tg.parallel()
  1807  
  1808  	tg.tempFile("p/src/p/main.go", `package main
  1809  		// #cgo FFLAGS: -no-such-fortran-flag
  1810  		import "C"
  1811  		func main() {}
  1812  	`)
  1813  	tg.tempFile("p/src/p/a.f", `! comment`)
  1814  	tg.setenv("GOPATH", tg.path("p"))
  1815  
  1816  	// This should normally fail because we are passing an unknown flag,
  1817  	// but issue #19080 points to Fortran compilers that succeed anyhow.
  1818  	// To work either way we call doRun directly rather than run or runFail.
  1819  	tg.doRun([]string{"build", "-x", "p"})
  1820  
  1821  	tg.grepStderr("no-such-fortran-flag", `missing expected "-no-such-fortran-flag"`)
  1822  }
  1823  
  1824  // Issue 19198.
  1825  // This is really a cmd/link issue but this is a convenient place to test it.
  1826  func TestDuplicateGlobalAsmSymbols(t *testing.T) {
  1827  	skipIfGccgo(t, "gccgo does not use cmd/asm")
  1828  	tooSlow(t, "links a binary with cgo dependencies")
  1829  	if runtime.GOARCH != "386" && runtime.GOARCH != "amd64" {
  1830  		t.Skipf("skipping test on %s", runtime.GOARCH)
  1831  	}
  1832  	testenv.MustHaveCGO(t)
  1833  
  1834  	tg := testgo(t)
  1835  	defer tg.cleanup()
  1836  	tg.parallel()
  1837  
  1838  	asm := `
  1839  #include "textflag.h"
  1840  
  1841  DATA sym<>+0x0(SB)/8,$0
  1842  GLOBL sym<>(SB),(NOPTR+RODATA),$8
  1843  
  1844  TEXT ·Data(SB),NOSPLIT,$0
  1845  	MOVB sym<>(SB), AX
  1846  	MOVB AX, ret+0(FP)
  1847  	RET
  1848  `
  1849  	tg.tempFile("go/src/a/a.s", asm)
  1850  	tg.tempFile("go/src/a/a.go", `package a; func Data() uint8`)
  1851  	tg.tempFile("go/src/b/b.s", asm)
  1852  	tg.tempFile("go/src/b/b.go", `package b; func Data() uint8`)
  1853  	tg.tempFile("go/src/p/p.go", `
  1854  package main
  1855  import "a"
  1856  import "b"
  1857  import "C"
  1858  func main() {
  1859  	_ = a.Data() + b.Data()
  1860  }
  1861  `)
  1862  	tg.setenv("GOPATH", tg.path("go"))
  1863  	exe := tg.path("p.exe")
  1864  	tg.creatingTemp(exe)
  1865  	tg.run("build", "-o", exe, "p")
  1866  }
  1867  
  1868  func copyFile(src, dst string, perm fs.FileMode) error {
  1869  	sf, err := os.Open(src)
  1870  	if err != nil {
  1871  		return err
  1872  	}
  1873  	defer sf.Close()
  1874  
  1875  	df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
  1876  	if err != nil {
  1877  		return err
  1878  	}
  1879  
  1880  	_, err = io.Copy(df, sf)
  1881  	err2 := df.Close()
  1882  	if err != nil {
  1883  		return err
  1884  	}
  1885  	return err2
  1886  }
  1887  
  1888  func TestNeedVersion(t *testing.T) {
  1889  	skipIfGccgo(t, "gccgo does not use cmd/compile")
  1890  	tg := testgo(t)
  1891  	defer tg.cleanup()
  1892  	tg.parallel()
  1893  	tg.tempFile("goversion.go", `package main; func main() {}`)
  1894  	path := tg.path("goversion.go")
  1895  	tg.setenv("TESTGO_TOOLCHAIN_VERSION", "go1.testgo")
  1896  	tg.runFail("run", path)
  1897  	tg.grepStderr("compile", "does not match go tool version")
  1898  }
  1899  
  1900  func TestBuildmodePIE(t *testing.T) {
  1901  	tooSlow(t, "links binaries")
  1902  	t.Parallel()
  1903  
  1904  	if !platform.BuildModeSupported(runtime.Compiler, "pie", runtime.GOOS, runtime.GOARCH) {
  1905  		t.Skipf("skipping test because buildmode=pie is not supported on %s/%s", runtime.GOOS, runtime.GOARCH)
  1906  	}
  1907  	// Skip on alpine until https://go.dev/issues/54354 resolved.
  1908  	if strings.HasSuffix(testenv.Builder(), "-alpine") {
  1909  		t.Skip("skipping PIE tests on alpine; see https://go.dev/issues/54354")
  1910  	}
  1911  	t.Run("non-cgo", func(t *testing.T) {
  1912  		testBuildmodePIE(t, false, true)
  1913  	})
  1914  	t.Run("cgo", func(t *testing.T) {
  1915  		testenv.MustHaveCGO(t)
  1916  		testBuildmodePIE(t, true, true)
  1917  	})
  1918  }
  1919  
  1920  func TestWindowsDefaultBuildmodIsPIE(t *testing.T) {
  1921  	if runtime.GOOS != "windows" {
  1922  		t.Skip("skipping windows only test")
  1923  	}
  1924  	tooSlow(t, "links binaries")
  1925  	t.Parallel()
  1926  
  1927  	t.Run("non-cgo", func(t *testing.T) {
  1928  		testBuildmodePIE(t, false, false)
  1929  	})
  1930  	t.Run("cgo", func(t *testing.T) {
  1931  		testenv.MustHaveCGO(t)
  1932  		testBuildmodePIE(t, true, false)
  1933  	})
  1934  }
  1935  
  1936  func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) {
  1937  	tg := testgo(t)
  1938  	defer tg.cleanup()
  1939  	tg.parallel()
  1940  
  1941  	var s string
  1942  	if useCgo {
  1943  		s = `import "C";`
  1944  	}
  1945  	tg.tempFile("main.go", fmt.Sprintf(`package main;%s func main() { print("hello") }`, s))
  1946  	src := tg.path("main.go")
  1947  	obj := tg.path("main.exe")
  1948  	args := []string{"build"}
  1949  	if setBuildmodeToPIE {
  1950  		args = append(args, "-buildmode=pie")
  1951  	}
  1952  	args = append(args, "-o", obj, src)
  1953  	tg.run(args...)
  1954  
  1955  	switch runtime.GOOS {
  1956  	case "linux", "android", "freebsd":
  1957  		f, err := elf.Open(obj)
  1958  		if err != nil {
  1959  			t.Fatal(err)
  1960  		}
  1961  		defer f.Close()
  1962  		if f.Type != elf.ET_DYN {
  1963  			t.Errorf("PIE type must be ET_DYN, but %s", f.Type)
  1964  		}
  1965  	case "darwin", "ios":
  1966  		f, err := macho.Open(obj)
  1967  		if err != nil {
  1968  			t.Fatal(err)
  1969  		}
  1970  		defer f.Close()
  1971  		if f.Flags&macho.FlagDyldLink == 0 {
  1972  			t.Error("PIE must have DyldLink flag, but not")
  1973  		}
  1974  		if f.Flags&macho.FlagPIE == 0 {
  1975  			t.Error("PIE must have PIE flag, but not")
  1976  		}
  1977  	case "windows":
  1978  		f, err := pe.Open(obj)
  1979  		if err != nil {
  1980  			t.Fatal(err)
  1981  		}
  1982  		defer f.Close()
  1983  		if f.Section(".reloc") == nil {
  1984  			t.Error(".reloc section is not present")
  1985  		}
  1986  		if (f.FileHeader.Characteristics & pe.IMAGE_FILE_RELOCS_STRIPPED) != 0 {
  1987  			t.Error("IMAGE_FILE_RELOCS_STRIPPED flag is set")
  1988  		}
  1989  		var dc uint16
  1990  		switch oh := f.OptionalHeader.(type) {
  1991  		case *pe.OptionalHeader32:
  1992  			dc = oh.DllCharacteristics
  1993  		case *pe.OptionalHeader64:
  1994  			dc = oh.DllCharacteristics
  1995  			if (dc & pe.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) == 0 {
  1996  				t.Error("IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA flag is not set")
  1997  			}
  1998  		default:
  1999  			t.Fatalf("unexpected optional header type of %T", f.OptionalHeader)
  2000  		}
  2001  		if (dc & pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 {
  2002  			t.Error("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag is not set")
  2003  		}
  2004  	default:
  2005  		// testBuildmodePIE opens object files, so it needs to understand the object
  2006  		// file format.
  2007  		t.Skipf("skipping test: test helper does not support %s", runtime.GOOS)
  2008  	}
  2009  
  2010  	out, err := testenv.Command(t, obj).CombinedOutput()
  2011  	if err != nil {
  2012  		t.Fatal(err)
  2013  	}
  2014  
  2015  	if string(out) != "hello" {
  2016  		t.Errorf("got %q; want %q", out, "hello")
  2017  	}
  2018  }
  2019  
  2020  func TestUpxCompression(t *testing.T) {
  2021  	if runtime.GOOS != "linux" ||
  2022  		(runtime.GOARCH != "amd64" && runtime.GOARCH != "386") {
  2023  		t.Skipf("skipping upx test on %s/%s", runtime.GOOS, runtime.GOARCH)
  2024  	}
  2025  
  2026  	testenv.MustHaveExecPath(t, "upx")
  2027  	out, err := testenv.Command(t, "upx", "--version").CombinedOutput()
  2028  	if err != nil {
  2029  		t.Fatalf("upx --version failed: %v", err)
  2030  	}
  2031  
  2032  	// upx --version prints `upx <version>` in the first line of output:
  2033  	//   upx 3.94
  2034  	//   [...]
  2035  	re := regexp.MustCompile(`([[:digit:]]+)\.([[:digit:]]+)`)
  2036  	upxVersion := re.FindStringSubmatch(string(out))
  2037  	if len(upxVersion) != 3 {
  2038  		t.Fatalf("bad upx version string: %s", upxVersion)
  2039  	}
  2040  
  2041  	major, err1 := strconv.Atoi(upxVersion[1])
  2042  	minor, err2 := strconv.Atoi(upxVersion[2])
  2043  	if err1 != nil || err2 != nil {
  2044  		t.Fatalf("bad upx version string: %s", upxVersion[0])
  2045  	}
  2046  
  2047  	// Anything below 3.94 is known not to work with go binaries
  2048  	if (major < 3) || (major == 3 && minor < 94) {
  2049  		t.Skipf("skipping because upx version %v.%v is too old", major, minor)
  2050  	}
  2051  
  2052  	tg := testgo(t)
  2053  	defer tg.cleanup()
  2054  	tg.parallel()
  2055  
  2056  	tg.tempFile("main.go", `package main; import "fmt"; func main() { fmt.Print("hello upx") }`)
  2057  	src := tg.path("main.go")
  2058  	obj := tg.path("main")
  2059  	tg.run("build", "-o", obj, src)
  2060  
  2061  	out, err = testenv.Command(t, "upx", obj).CombinedOutput()
  2062  	if err != nil {
  2063  		t.Logf("executing upx\n%s\n", out)
  2064  		t.Fatalf("upx failed with %v", err)
  2065  	}
  2066  
  2067  	out, err = testenv.Command(t, obj).CombinedOutput()
  2068  	if err != nil {
  2069  		t.Logf("%s", out)
  2070  		t.Fatalf("running compressed go binary failed with error %s", err)
  2071  	}
  2072  	if string(out) != "hello upx" {
  2073  		t.Fatalf("bad output from compressed go binary:\ngot %q; want %q", out, "hello upx")
  2074  	}
  2075  }
  2076  
  2077  var gocacheverify = godebug.New("#gocacheverify")
  2078  
  2079  func TestCacheListStale(t *testing.T) {
  2080  	tooSlow(t, "links a binary")
  2081  	if gocacheverify.Value() == "1" {
  2082  		t.Skip("GODEBUG gocacheverify")
  2083  	}
  2084  
  2085  	tg := testgo(t)
  2086  	defer tg.cleanup()
  2087  	tg.parallel()
  2088  	tg.makeTempdir()
  2089  	tg.setenv("GOCACHE", tg.path("cache"))
  2090  	tg.tempFile("gopath/src/p/p.go", "package p; import _ \"q\"; func F(){}\n")
  2091  	tg.tempFile("gopath/src/q/q.go", "package q; func F(){}\n")
  2092  	tg.tempFile("gopath/src/m/m.go", "package main; import _ \"q\"; func main(){}\n")
  2093  
  2094  	tg.setenv("GOPATH", tg.path("gopath"))
  2095  	tg.run("install", "p", "m")
  2096  	tg.run("list", "-f={{.ImportPath}} {{.Stale}}", "m", "q", "p")
  2097  	tg.grepStdout("^m false", "m should not be stale")
  2098  	tg.grepStdout("^q true", "q should be stale")
  2099  	tg.grepStdout("^p false", "p should not be stale")
  2100  }
  2101  
  2102  func TestCacheCoverage(t *testing.T) {
  2103  	tooSlow(t, "links and runs a test binary with coverage enabled")
  2104  	if gocacheverify.Value() == "1" {
  2105  		t.Skip("GODEBUG gocacheverify")
  2106  	}
  2107  
  2108  	tg := testgo(t)
  2109  	defer tg.cleanup()
  2110  	tg.parallel()
  2111  	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
  2112  	tg.makeTempdir()
  2113  
  2114  	tg.setenv("GOCACHE", tg.path("c1"))
  2115  	tg.run("test", "-cover", "-short", "strings")
  2116  	tg.run("test", "-cover", "-short", "math", "strings")
  2117  }
  2118  
  2119  func TestIssue22531(t *testing.T) {
  2120  	tooSlow(t, "links binaries")
  2121  	if gocacheverify.Value() == "1" {
  2122  		t.Skip("GODEBUG gocacheverify")
  2123  	}
  2124  
  2125  	tg := testgo(t)
  2126  	defer tg.cleanup()
  2127  	tg.parallel()
  2128  	tg.makeTempdir()
  2129  	tg.setenv("GOPATH", tg.tempdir)
  2130  	tg.setenv("GOCACHE", tg.path("cache"))
  2131  	tg.tempFile("src/m/main.go", "package main /* c1 */; func main() {}\n")
  2132  	tg.run("install", "-x", "m")
  2133  	tg.run("list", "-f", "{{.Stale}}", "m")
  2134  	tg.grepStdout("false", "reported m as stale after install")
  2135  	tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix))
  2136  
  2137  	// The link action ID did not include the full main build ID,
  2138  	// even though the full main build ID is written into the
  2139  	// eventual binary. That caused the following install to
  2140  	// be a no-op, thinking the gofmt binary was up-to-date,
  2141  	// even though .Stale could see it was not.
  2142  	tg.tempFile("src/m/main.go", "package main /* c2 */; func main() {}\n")
  2143  	tg.run("install", "-x", "m")
  2144  	tg.run("list", "-f", "{{.Stale}}", "m")
  2145  	tg.grepStdout("false", "reported m as stale after reinstall")
  2146  	tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix))
  2147  }
  2148  
  2149  func TestIssue22596(t *testing.T) {
  2150  	tooSlow(t, "links binaries")
  2151  	if gocacheverify.Value() == "1" {
  2152  		t.Skip("GODEBUG gocacheverify")
  2153  	}
  2154  
  2155  	tg := testgo(t)
  2156  	defer tg.cleanup()
  2157  	tg.parallel()
  2158  	tg.makeTempdir()
  2159  	tg.setenv("GOCACHE", tg.path("cache"))
  2160  	tg.tempFile("gopath1/src/p/p.go", "package p; func F(){}\n")
  2161  	tg.tempFile("gopath2/src/p/p.go", "package p; func F(){}\n")
  2162  
  2163  	tg.setenv("GOPATH", tg.path("gopath1"))
  2164  	tg.run("list", "-f={{.Target}}", "p")
  2165  	target1 := strings.TrimSpace(tg.getStdout())
  2166  	tg.run("install", "p")
  2167  	tg.wantNotStale("p", "", "p stale after install")
  2168  
  2169  	tg.setenv("GOPATH", tg.path("gopath2"))
  2170  	tg.run("list", "-f={{.Target}}", "p")
  2171  	target2 := strings.TrimSpace(tg.getStdout())
  2172  	tg.must(os.MkdirAll(filepath.Dir(target2), 0777))
  2173  	tg.must(copyFile(target1, target2, 0666))
  2174  	tg.wantStale("p", "build ID mismatch", "p not stale after copy from gopath1")
  2175  	tg.run("install", "p")
  2176  	tg.wantNotStale("p", "", "p stale after install2")
  2177  }
  2178  
  2179  func TestTestCache(t *testing.T) {
  2180  	tooSlow(t, "links and runs test binaries")
  2181  	if gocacheverify.Value() == "1" {
  2182  		t.Skip("GODEBUG gocacheverify")
  2183  	}
  2184  
  2185  	tg := testgo(t)
  2186  	defer tg.cleanup()
  2187  	tg.parallel()
  2188  	tg.makeTempdir()
  2189  	tg.setenv("GOPATH", tg.tempdir)
  2190  	tg.setenv("GOCACHE", tg.path("cache"))
  2191  
  2192  	// The -p=1 in the commands below just makes the -x output easier to read.
  2193  
  2194  	t.Log("\n\nINITIAL\n\n")
  2195  
  2196  	tg.tempFile("src/p1/p1.go", "package p1\nvar X =  1\n")
  2197  	tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\nvar X = 1\n")
  2198  	tg.tempFile("src/t/t1/t1_test.go", "package t\nimport \"testing\"\nfunc Test1(*testing.T) {}\n")
  2199  	tg.tempFile("src/t/t2/t2_test.go", "package t\nimport _ \"p1\"\nimport \"testing\"\nfunc Test2(*testing.T) {}\n")
  2200  	tg.tempFile("src/t/t3/t3_test.go", "package t\nimport \"p1\"\nimport \"testing\"\nfunc Test3(t *testing.T) {t.Log(p1.X)}\n")
  2201  	tg.tempFile("src/t/t4/t4_test.go", "package t\nimport \"p2\"\nimport \"testing\"\nfunc Test4(t *testing.T) {t.Log(p2.X)}")
  2202  	tg.run("test", "-x", "-v", "-short", "t/...")
  2203  
  2204  	t.Log("\n\nREPEAT\n\n")
  2205  
  2206  	tg.run("test", "-x", "-v", "-short", "t/...")
  2207  	tg.grepStdout(`ok  \tt/t1\t\(cached\)`, "did not cache t1")
  2208  	tg.grepStdout(`ok  \tt/t2\t\(cached\)`, "did not cache t2")
  2209  	tg.grepStdout(`ok  \tt/t3\t\(cached\)`, "did not cache t3")
  2210  	tg.grepStdout(`ok  \tt/t4\t\(cached\)`, "did not cache t4")
  2211  	tg.grepStderrNot(`[\\/](compile|gccgo) `, "incorrectly ran compiler")
  2212  	tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker")
  2213  	tg.grepStderrNot(`p[0-9]\.test`, "incorrectly ran test")
  2214  
  2215  	t.Log("\n\nCOMMENT\n\n")
  2216  
  2217  	// Changing the program text without affecting the compiled package
  2218  	// should result in the package being rebuilt but nothing more.
  2219  	tg.tempFile("src/p1/p1.go", "package p1\nvar X = 01\n")
  2220  	tg.run("test", "-p=1", "-x", "-v", "-short", "t/...")
  2221  	tg.grepStdout(`ok  \tt/t1\t\(cached\)`, "did not cache t1")
  2222  	tg.grepStdout(`ok  \tt/t2\t\(cached\)`, "did not cache t2")
  2223  	tg.grepStdout(`ok  \tt/t3\t\(cached\)`, "did not cache t3")
  2224  	tg.grepStdout(`ok  \tt/t4\t\(cached\)`, "did not cache t4")
  2225  	tg.grepStderrNot(`([\\/](compile|gccgo) ).*t[0-9]_test\.go`, "incorrectly ran compiler")
  2226  	tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker")
  2227  	tg.grepStderrNot(`t[0-9]\.test.*test\.short`, "incorrectly ran test")
  2228  
  2229  	t.Log("\n\nCHANGE\n\n")
  2230  
  2231  	// Changing the actual package should have limited effects.
  2232  	tg.tempFile("src/p1/p1.go", "package p1\nvar X = 02\n")
  2233  	tg.run("test", "-p=1", "-x", "-v", "-short", "t/...")
  2234  
  2235  	// p2 should have been rebuilt.
  2236  	tg.grepStderr(`([\\/]compile|gccgo).*p2.go`, "did not recompile p2")
  2237  
  2238  	// t1 does not import anything, should not have been rebuilt.
  2239  	tg.grepStderrNot(`([\\/]compile|gccgo).*t1_test.go`, "incorrectly recompiled t1")
  2240  	tg.grepStderrNot(`([\\/]link|gccgo).*t1_test`, "incorrectly relinked t1_test")
  2241  	tg.grepStdout(`ok  \tt/t1\t\(cached\)`, "did not cache t/t1")
  2242  
  2243  	// t2 imports p1 and must be rebuilt and relinked,
  2244  	// but the change should not have any effect on the test binary,
  2245  	// so the test should not have been rerun.
  2246  	tg.grepStderr(`([\\/]compile|gccgo).*t2_test.go`, "did not recompile t2")
  2247  	tg.grepStderr(`([\\/]link|gccgo).*t2\.test`, "did not relink t2_test")
  2248  	// This check does not currently work with gccgo, as garbage
  2249  	// collection of unused variables is not turned on by default.
  2250  	if runtime.Compiler != "gccgo" {
  2251  		tg.grepStdout(`ok  \tt/t2\t\(cached\)`, "did not cache t/t2")
  2252  	}
  2253  
  2254  	// t3 imports p1, and changing X changes t3's test binary.
  2255  	tg.grepStderr(`([\\/]compile|gccgo).*t3_test.go`, "did not recompile t3")
  2256  	tg.grepStderr(`([\\/]link|gccgo).*t3\.test`, "did not relink t3_test")
  2257  	tg.grepStderr(`t3\.test.*-test.short`, "did not rerun t3_test")
  2258  	tg.grepStdoutNot(`ok  \tt/t3\t\(cached\)`, "reported cached t3_test result")
  2259  
  2260  	// t4 imports p2, but p2 did not change, so t4 should be relinked, not recompiled,
  2261  	// and not rerun.
  2262  	tg.grepStderrNot(`([\\/]compile|gccgo).*t4_test.go`, "incorrectly recompiled t4")
  2263  	tg.grepStderr(`([\\/]link|gccgo).*t4\.test`, "did not relink t4_test")
  2264  	// This check does not currently work with gccgo, as garbage
  2265  	// collection of unused variables is not turned on by default.
  2266  	if runtime.Compiler != "gccgo" {
  2267  		tg.grepStdout(`ok  \tt/t4\t\(cached\)`, "did not cache t/t4")
  2268  	}
  2269  }
  2270  
  2271  func TestTestSkipVetAfterFailedBuild(t *testing.T) {
  2272  	tg := testgo(t)
  2273  	defer tg.cleanup()
  2274  	tg.parallel()
  2275  
  2276  	tg.tempFile("x_test.go", `package x
  2277  		func f() {
  2278  			return 1
  2279  		}
  2280  	`)
  2281  
  2282  	tg.runFail("test", tg.path("x_test.go"))
  2283  	tg.grepStderrNot(`vet`, "vet should be skipped after the failed build")
  2284  }
  2285  
  2286  func TestTestVetRebuild(t *testing.T) {
  2287  	tooSlow(t, "links and runs test binaries")
  2288  
  2289  	tg := testgo(t)
  2290  	defer tg.cleanup()
  2291  	tg.parallel()
  2292  
  2293  	// golang.org/issue/23701.
  2294  	// b_test imports b with augmented method from export_test.go.
  2295  	// b_test also imports a, which imports b.
  2296  	// Must not accidentally see un-augmented b propagate through a to b_test.
  2297  	tg.tempFile("src/a/a.go", `package a
  2298  		import "b"
  2299  		type Type struct{}
  2300  		func (*Type) M() b.T {return 0}
  2301  	`)
  2302  	tg.tempFile("src/b/b.go", `package b
  2303  		type T int
  2304  		type I interface {M() T}
  2305  	`)
  2306  	tg.tempFile("src/b/export_test.go", `package b
  2307  		func (*T) Method() *T { return nil }
  2308  	`)
  2309  	tg.tempFile("src/b/b_test.go", `package b_test
  2310  		import (
  2311  			"testing"
  2312  			"a"
  2313  			. "b"
  2314  		)
  2315  		func TestBroken(t *testing.T) {
  2316  			x := new(T)
  2317  			x.Method()
  2318  			_ = new(a.Type)
  2319  		}
  2320  	`)
  2321  
  2322  	tg.setenv("GOPATH", tg.path("."))
  2323  	tg.run("test", "b")
  2324  	tg.run("vet", "b")
  2325  }
  2326  
  2327  func TestInstallDeps(t *testing.T) {
  2328  	tooSlow(t, "links a binary")
  2329  
  2330  	tg := testgo(t)
  2331  	defer tg.cleanup()
  2332  	tg.parallel()
  2333  	tg.makeTempdir()
  2334  	tg.setenv("GOPATH", tg.tempdir)
  2335  
  2336  	tg.tempFile("src/p1/p1.go", "package p1\nvar X =  1\n")
  2337  	tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\n")
  2338  	tg.tempFile("src/main1/main.go", "package main\nimport _ \"p2\"\nfunc main() {}\n")
  2339  
  2340  	tg.run("list", "-f={{.Target}}", "p1")
  2341  	p1 := strings.TrimSpace(tg.getStdout())
  2342  	tg.run("list", "-f={{.Target}}", "p2")
  2343  	p2 := strings.TrimSpace(tg.getStdout())
  2344  	tg.run("list", "-f={{.Target}}", "main1")
  2345  	main1 := strings.TrimSpace(tg.getStdout())
  2346  
  2347  	tg.run("install", "main1")
  2348  
  2349  	tg.mustExist(main1)
  2350  	tg.mustNotExist(p2)
  2351  	tg.mustNotExist(p1)
  2352  
  2353  	tg.run("install", "p2")
  2354  	tg.mustExist(p2)
  2355  	tg.mustNotExist(p1)
  2356  }
  2357  
  2358  // Issue 22986.
  2359  func TestImportPath(t *testing.T) {
  2360  	tooSlow(t, "links and runs a test binary")
  2361  
  2362  	tg := testgo(t)
  2363  	defer tg.cleanup()
  2364  	tg.parallel()
  2365  
  2366  	tg.tempFile("src/a/a.go", `
  2367  package main
  2368  
  2369  import (
  2370  	"log"
  2371  	p "a/p-1.0"
  2372  )
  2373  
  2374  func main() {
  2375  	if !p.V {
  2376  		log.Fatal("false")
  2377  	}
  2378  }`)
  2379  
  2380  	tg.tempFile("src/a/a_test.go", `
  2381  package main_test
  2382  
  2383  import (
  2384  	p "a/p-1.0"
  2385  	"testing"
  2386  )
  2387  
  2388  func TestV(t *testing.T) {
  2389  	if !p.V {
  2390  		t.Fatal("false")
  2391  	}
  2392  }`)
  2393  
  2394  	tg.tempFile("src/a/p-1.0/p.go", `
  2395  package p
  2396  
  2397  var V = true
  2398  
  2399  func init() {}
  2400  `)
  2401  
  2402  	tg.setenv("GOPATH", tg.path("."))
  2403  	tg.run("build", "-o", tg.path("a.exe"), "a")
  2404  	tg.run("test", "a")
  2405  }
  2406  
  2407  func TestBadCommandLines(t *testing.T) {
  2408  	tg := testgo(t)
  2409  	defer tg.cleanup()
  2410  	tg.parallel()
  2411  
  2412  	tg.tempFile("src/x/x.go", "package x\n")
  2413  	tg.setenv("GOPATH", tg.path("."))
  2414  
  2415  	tg.run("build", "x")
  2416  
  2417  	tg.tempFile("src/x/@y.go", "package x\n")
  2418  	tg.runFail("build", "x")
  2419  	tg.grepStderr("invalid input file name \"@y.go\"", "did not reject @y.go")
  2420  	tg.must(os.Remove(tg.path("src/x/@y.go")))
  2421  
  2422  	tg.tempFile("src/x/-y.go", "package x\n")
  2423  	tg.runFail("build", "x")
  2424  	tg.grepStderr("invalid input file name \"-y.go\"", "did not reject -y.go")
  2425  	tg.must(os.Remove(tg.path("src/x/-y.go")))
  2426  
  2427  	if runtime.Compiler == "gccgo" {
  2428  		tg.runFail("build", "-gccgoflags=all=@x", "x")
  2429  	} else {
  2430  		tg.runFail("build", "-gcflags=all=@x", "x")
  2431  	}
  2432  	tg.grepStderr("invalid command-line argument @x in command", "did not reject @x during exec")
  2433  
  2434  	tg.tempFile("src/@x/x.go", "package x\n")
  2435  	tg.setenv("GOPATH", tg.path("."))
  2436  	tg.runFail("build", "@x")
  2437  	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")
  2438  
  2439  	tg.tempFile("src/@x/y/y.go", "package y\n")
  2440  	tg.setenv("GOPATH", tg.path("."))
  2441  	tg.runFail("build", "@x/y")
  2442  	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")
  2443  
  2444  	tg.tempFile("src/-x/x.go", "package x\n")
  2445  	tg.setenv("GOPATH", tg.path("."))
  2446  	tg.runFail("build", "--", "-x")
  2447  	tg.grepStderr("invalid import path \"-x\"", "did not reject -x import path")
  2448  
  2449  	tg.tempFile("src/-x/y/y.go", "package y\n")
  2450  	tg.setenv("GOPATH", tg.path("."))
  2451  	tg.runFail("build", "--", "-x/y")
  2452  	tg.grepStderr("invalid import path \"-x/y\"", "did not reject -x/y import path")
  2453  }
  2454  
  2455  func TestTwoPkgConfigs(t *testing.T) {
  2456  	testenv.MustHaveCGO(t)
  2457  	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
  2458  		t.Skipf("no shell scripts on %s", runtime.GOOS)
  2459  	}
  2460  	tooSlow(t, "builds a package with cgo dependencies")
  2461  
  2462  	tg := testgo(t)
  2463  	defer tg.cleanup()
  2464  	tg.parallel()
  2465  	tg.tempFile("src/x/a.go", `package x
  2466  		// #cgo pkg-config: --static a
  2467  		import "C"
  2468  	`)
  2469  	tg.tempFile("src/x/b.go", `package x
  2470  		// #cgo pkg-config: --static a
  2471  		import "C"
  2472  	`)
  2473  	tg.tempFile("pkg-config.sh", `#!/bin/sh
  2474  echo $* >>`+tg.path("pkg-config.out"))
  2475  	tg.must(os.Chmod(tg.path("pkg-config.sh"), 0755))
  2476  	tg.setenv("GOPATH", tg.path("."))
  2477  	tg.setenv("PKG_CONFIG", tg.path("pkg-config.sh"))
  2478  	tg.run("build", "x")
  2479  	out, err := os.ReadFile(tg.path("pkg-config.out"))
  2480  	tg.must(err)
  2481  	out = bytes.TrimSpace(out)
  2482  	want := "--cflags --static --static -- a a\n--libs --static --static -- a a"
  2483  	if !bytes.Equal(out, []byte(want)) {
  2484  		t.Errorf("got %q want %q", out, want)
  2485  	}
  2486  }
  2487  
  2488  func TestCgoCache(t *testing.T) {
  2489  	testenv.MustHaveCGO(t)
  2490  	tooSlow(t, "builds a package with cgo dependencies")
  2491  
  2492  	tg := testgo(t)
  2493  	defer tg.cleanup()
  2494  	tg.parallel()
  2495  	tg.tempFile("src/x/a.go", `package main
  2496  		// #ifndef VAL
  2497  		// #define VAL 0
  2498  		// #endif
  2499  		// int val = VAL;
  2500  		import "C"
  2501  		import "fmt"
  2502  		func main() { fmt.Println(C.val) }
  2503  	`)
  2504  	tg.setenv("GOPATH", tg.path("."))
  2505  	exe := tg.path("x.exe")
  2506  	tg.run("build", "-o", exe, "x")
  2507  	tg.setenv("CGO_LDFLAGS", "-lnosuchlibraryexists")
  2508  	tg.runFail("build", "-o", exe, "x")
  2509  	tg.grepStderr(`nosuchlibraryexists`, "did not run linker with changed CGO_LDFLAGS")
  2510  }
  2511  
  2512  // Issue 23982
  2513  func TestFilepathUnderCwdFormat(t *testing.T) {
  2514  	tg := testgo(t)
  2515  	defer tg.cleanup()
  2516  	tg.parallel()
  2517  	tg.run("test", "-x", "-cover", "log")
  2518  	tg.grepStderrNot(`\.log\.cover\.go`, "-x output should contain correctly formatted filepath under cwd")
  2519  }
  2520  
  2521  // Issue 24396.
  2522  func TestDontReportRemoveOfEmptyDir(t *testing.T) {
  2523  	tg := testgo(t)
  2524  	defer tg.cleanup()
  2525  	tg.parallel()
  2526  	tg.tempFile("src/a/a.go", `package a`)
  2527  	tg.setenv("GOPATH", tg.path("."))
  2528  	tg.run("install", "-x", "a")
  2529  	tg.run("install", "-x", "a")
  2530  	// The second install should have printed only a WORK= line,
  2531  	// nothing else.
  2532  	if bytes.Count(tg.stdout.Bytes(), []byte{'\n'})+bytes.Count(tg.stderr.Bytes(), []byte{'\n'}) > 1 {
  2533  		t.Error("unnecessary output when installing installed package")
  2534  	}
  2535  }
  2536  
  2537  // Issue 24704.
  2538  func TestLinkerTmpDirIsDeleted(t *testing.T) {
  2539  	skipIfGccgo(t, "gccgo does not use cmd/link")
  2540  	testenv.MustHaveCGO(t)
  2541  	tooSlow(t, "builds a package with cgo dependencies")
  2542  
  2543  	tg := testgo(t)
  2544  	defer tg.cleanup()
  2545  	tg.parallel()
  2546  	tg.tempFile("a.go", `package main; import "C"; func main() {}`)
  2547  	tg.run("build", "-ldflags", "-v", "-o", os.DevNull, tg.path("a.go"))
  2548  	// Find line that has "host link:" in linker output.
  2549  	stderr := tg.getStderr()
  2550  	var hostLinkLine string
  2551  	for _, line := range strings.Split(stderr, "\n") {
  2552  		if !strings.Contains(line, "host link:") {
  2553  			continue
  2554  		}
  2555  		hostLinkLine = line
  2556  		break
  2557  	}
  2558  	if hostLinkLine == "" {
  2559  		t.Fatal(`fail to find with "host link:" string in linker output`)
  2560  	}
  2561  	// Find parameter, like "/tmp/go-link-408556474/go.o" inside of
  2562  	// "host link:" line, and extract temp directory /tmp/go-link-408556474
  2563  	// out of it.
  2564  	tmpdir := hostLinkLine
  2565  	i := strings.Index(tmpdir, `go.o"`)
  2566  	if i == -1 {
  2567  		t.Fatalf(`fail to find "go.o" in "host link:" line %q`, hostLinkLine)
  2568  	}
  2569  	tmpdir = tmpdir[:i-1]
  2570  	i = strings.LastIndex(tmpdir, `"`)
  2571  	if i == -1 {
  2572  		t.Fatalf(`fail to find " in "host link:" line %q`, hostLinkLine)
  2573  	}
  2574  	tmpdir = tmpdir[i+1:]
  2575  	// Verify that temp directory has been removed.
  2576  	_, err := os.Stat(tmpdir)
  2577  	if err == nil {
  2578  		t.Fatalf("temp directory %q has not been removed", tmpdir)
  2579  	}
  2580  	if !os.IsNotExist(err) {
  2581  		t.Fatalf("Stat(%q) returns unexpected error: %v", tmpdir, err)
  2582  	}
  2583  }
  2584  
  2585  // Issue 25093.
  2586  func TestCoverpkgTestOnly(t *testing.T) {
  2587  	skipIfGccgo(t, "gccgo has no cover tool")
  2588  	tooSlow(t, "links and runs a test binary with coverage enabled")
  2589  
  2590  	tg := testgo(t)
  2591  	defer tg.cleanup()
  2592  	tg.parallel()
  2593  	tg.tempFile("src/a/a.go", `package a
  2594  		func F(i int) int {
  2595  			return i*i
  2596  		}`)
  2597  	tg.tempFile("src/atest/a_test.go", `
  2598  		package a_test
  2599  		import ( "a"; "testing" )
  2600  		func TestF(t *testing.T) { a.F(2) }
  2601  	`)
  2602  	tg.setenv("GOPATH", tg.path("."))
  2603  	tg.run("test", "-coverpkg=a", "atest")
  2604  	tg.grepStderrNot("no packages being tested depend on matches", "bad match message")
  2605  	tg.grepStdout("coverage: 100", "no coverage")
  2606  }
  2607  

View as plain text