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  		for _, arg := range args {
   492  			if strings.HasPrefix(arg, "testdata") || strings.HasPrefix(arg, "./testdata") {
   493  				tg.t.Fatal("internal testsuite error: parallel run using testdata")
   494  			}
   495  		}
   496  	}
   497  
   498  	hasGoroot := false
   499  	for _, v := range tg.env {
   500  		if strings.HasPrefix(v, "GOROOT=") {
   501  			hasGoroot = true
   502  			break
   503  		}
   504  	}
   505  	prog := tg.goTool()
   506  	if !hasGoroot {
   507  		tg.setenv("GOROOT", testGOROOT)
   508  	}
   509  
   510  	tg.t.Logf("running testgo %v", args)
   511  	cmd := testenv.Command(tg.t, prog, args...)
   512  	tg.stdout.Reset()
   513  	tg.stderr.Reset()
   514  	cmd.Dir = tg.execDir
   515  	cmd.Stdout = &tg.stdout
   516  	cmd.Stderr = &tg.stderr
   517  	cmd.Env = tg.env
   518  	status := cmd.Run()
   519  	if tg.stdout.Len() > 0 {
   520  		tg.t.Log("standard output:")
   521  		tg.t.Log(tg.stdout.String())
   522  	}
   523  	if tg.stderr.Len() > 0 {
   524  		tg.t.Log("standard error:")
   525  		tg.t.Log(tg.stderr.String())
   526  	}
   527  	tg.ran = true
   528  	return status
   529  }
   530  
   531  // run runs the test go command, and expects it to succeed.
   532  func (tg *testgoData) run(args ...string) {
   533  	tg.t.Helper()
   534  	if status := tg.doRun(args); status != nil {
   535  		wd, _ := os.Getwd()
   536  		tg.t.Logf("go %v failed unexpectedly in %s: %v", args, wd, status)
   537  		tg.t.FailNow()
   538  	}
   539  }
   540  
   541  // runFail runs the test go command, and expects it to fail.
   542  func (tg *testgoData) runFail(args ...string) {
   543  	tg.t.Helper()
   544  	if status := tg.doRun(args); status == nil {
   545  		tg.t.Fatal("testgo succeeded unexpectedly")
   546  	} else {
   547  		tg.t.Log("testgo failed as expected:", status)
   548  	}
   549  }
   550  
   551  // getStdout returns standard output of the testgo run as a string.
   552  func (tg *testgoData) getStdout() string {
   553  	tg.t.Helper()
   554  	if !tg.ran {
   555  		tg.t.Fatal("internal testsuite error: stdout called before run")
   556  	}
   557  	return tg.stdout.String()
   558  }
   559  
   560  // getStderr returns standard error of the testgo run as a string.
   561  func (tg *testgoData) getStderr() string {
   562  	tg.t.Helper()
   563  	if !tg.ran {
   564  		tg.t.Fatal("internal testsuite error: stdout called before run")
   565  	}
   566  	return tg.stderr.String()
   567  }
   568  
   569  // doGrepMatch looks for a regular expression in a buffer, and returns
   570  // whether it is found. The regular expression is matched against
   571  // each line separately, as with the grep command.
   572  func (tg *testgoData) doGrepMatch(match string, b *bytes.Buffer) bool {
   573  	tg.t.Helper()
   574  	if !tg.ran {
   575  		tg.t.Fatal("internal testsuite error: grep called before run")
   576  	}
   577  	re := regexp.MustCompile(match)
   578  	for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) {
   579  		if re.Match(ln) {
   580  			return true
   581  		}
   582  	}
   583  	return false
   584  }
   585  
   586  // doGrep looks for a regular expression in a buffer and fails if it
   587  // is not found. The name argument is the name of the output we are
   588  // searching, "output" or "error". The msg argument is logged on
   589  // failure.
   590  func (tg *testgoData) doGrep(match string, b *bytes.Buffer, name, msg string) {
   591  	tg.t.Helper()
   592  	if !tg.doGrepMatch(match, b) {
   593  		tg.t.Log(msg)
   594  		tg.t.Logf("pattern %v not found in standard %s", match, name)
   595  		tg.t.FailNow()
   596  	}
   597  }
   598  
   599  // grepStdout looks for a regular expression in the test run's
   600  // standard output and fails, logging msg, if it is not found.
   601  func (tg *testgoData) grepStdout(match, msg string) {
   602  	tg.t.Helper()
   603  	tg.doGrep(match, &tg.stdout, "output", msg)
   604  }
   605  
   606  // grepStderr looks for a regular expression in the test run's
   607  // standard error and fails, logging msg, if it is not found.
   608  func (tg *testgoData) grepStderr(match, msg string) {
   609  	tg.t.Helper()
   610  	tg.doGrep(match, &tg.stderr, "error", msg)
   611  }
   612  
   613  // grepBoth looks for a regular expression in the test run's standard
   614  // output or stand error and fails, logging msg, if it is not found.
   615  func (tg *testgoData) grepBoth(match, msg string) {
   616  	tg.t.Helper()
   617  	if !tg.doGrepMatch(match, &tg.stdout) && !tg.doGrepMatch(match, &tg.stderr) {
   618  		tg.t.Log(msg)
   619  		tg.t.Logf("pattern %v not found in standard output or standard error", match)
   620  		tg.t.FailNow()
   621  	}
   622  }
   623  
   624  // doGrepNot looks for a regular expression in a buffer and fails if
   625  // it is found. The name and msg arguments are as for doGrep.
   626  func (tg *testgoData) doGrepNot(match string, b *bytes.Buffer, name, msg string) {
   627  	tg.t.Helper()
   628  	if tg.doGrepMatch(match, b) {
   629  		tg.t.Log(msg)
   630  		tg.t.Logf("pattern %v found unexpectedly in standard %s", match, name)
   631  		tg.t.FailNow()
   632  	}
   633  }
   634  
   635  // grepStdoutNot looks for a regular expression in the test run's
   636  // standard output and fails, logging msg, if it is found.
   637  func (tg *testgoData) grepStdoutNot(match, msg string) {
   638  	tg.t.Helper()
   639  	tg.doGrepNot(match, &tg.stdout, "output", msg)
   640  }
   641  
   642  // grepStderrNot looks for a regular expression in the test run's
   643  // standard error and fails, logging msg, if it is found.
   644  func (tg *testgoData) grepStderrNot(match, msg string) {
   645  	tg.t.Helper()
   646  	tg.doGrepNot(match, &tg.stderr, "error", msg)
   647  }
   648  
   649  // grepBothNot looks for a regular expression in the test run's
   650  // standard output or standard error and fails, logging msg, if it is
   651  // found.
   652  func (tg *testgoData) grepBothNot(match, msg string) {
   653  	tg.t.Helper()
   654  	if tg.doGrepMatch(match, &tg.stdout) || tg.doGrepMatch(match, &tg.stderr) {
   655  		tg.t.Log(msg)
   656  		tg.t.Fatalf("pattern %v found unexpectedly in standard output or standard error", match)
   657  	}
   658  }
   659  
   660  // doGrepCount counts the number of times a regexp is seen in a buffer.
   661  func (tg *testgoData) doGrepCount(match string, b *bytes.Buffer) int {
   662  	tg.t.Helper()
   663  	if !tg.ran {
   664  		tg.t.Fatal("internal testsuite error: doGrepCount called before run")
   665  	}
   666  	re := regexp.MustCompile(match)
   667  	c := 0
   668  	for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) {
   669  		if re.Match(ln) {
   670  			c++
   671  		}
   672  	}
   673  	return c
   674  }
   675  
   676  // grepCountBoth returns the number of times a regexp is seen in both
   677  // standard output and standard error.
   678  func (tg *testgoData) grepCountBoth(match string) int {
   679  	tg.t.Helper()
   680  	return tg.doGrepCount(match, &tg.stdout) + tg.doGrepCount(match, &tg.stderr)
   681  }
   682  
   683  // creatingTemp records that the test plans to create a temporary file
   684  // or directory. If the file or directory exists already, it will be
   685  // removed. When the test completes, the file or directory will be
   686  // removed if it exists.
   687  func (tg *testgoData) creatingTemp(path string) {
   688  	tg.t.Helper()
   689  	if filepath.IsAbs(path) && !strings.HasPrefix(path, tg.tempdir) {
   690  		tg.t.Fatalf("internal testsuite error: creatingTemp(%q) with absolute path not in temporary directory", path)
   691  	}
   692  	tg.must(robustio.RemoveAll(path))
   693  	tg.temps = append(tg.temps, path)
   694  }
   695  
   696  // makeTempdir makes a temporary directory for a run of testgo. If
   697  // the temporary directory was already created, this does nothing.
   698  func (tg *testgoData) makeTempdir() {
   699  	tg.t.Helper()
   700  	if tg.tempdir == "" {
   701  		var err error
   702  		tg.tempdir, err = os.MkdirTemp("", "gotest")
   703  		tg.must(err)
   704  	}
   705  }
   706  
   707  // tempFile adds a temporary file for a run of testgo.
   708  func (tg *testgoData) tempFile(path, contents string) {
   709  	tg.t.Helper()
   710  	tg.makeTempdir()
   711  	tg.must(os.MkdirAll(filepath.Join(tg.tempdir, filepath.Dir(path)), 0755))
   712  	bytes := []byte(contents)
   713  	if strings.HasSuffix(path, ".go") {
   714  		formatted, err := format.Source(bytes)
   715  		if err == nil {
   716  			bytes = formatted
   717  		}
   718  	}
   719  	tg.must(os.WriteFile(filepath.Join(tg.tempdir, path), bytes, 0644))
   720  }
   721  
   722  // tempDir adds a temporary directory for a run of testgo.
   723  func (tg *testgoData) tempDir(path string) {
   724  	tg.t.Helper()
   725  	tg.makeTempdir()
   726  	if err := os.MkdirAll(filepath.Join(tg.tempdir, path), 0755); err != nil && !os.IsExist(err) {
   727  		tg.t.Fatal(err)
   728  	}
   729  }
   730  
   731  // path returns the absolute pathname to file with the temporary
   732  // directory.
   733  func (tg *testgoData) path(name string) string {
   734  	tg.t.Helper()
   735  	if tg.tempdir == "" {
   736  		tg.t.Fatalf("internal testsuite error: path(%q) with no tempdir", name)
   737  	}
   738  	if name == "." {
   739  		return tg.tempdir
   740  	}
   741  	return filepath.Join(tg.tempdir, name)
   742  }
   743  
   744  // mustExist fails if path does not exist.
   745  func (tg *testgoData) mustExist(path string) {
   746  	tg.t.Helper()
   747  	if _, err := os.Stat(path); err != nil {
   748  		if os.IsNotExist(err) {
   749  			tg.t.Fatalf("%s does not exist but should", path)
   750  		}
   751  		tg.t.Fatalf("%s stat failed: %v", path, err)
   752  	}
   753  }
   754  
   755  // mustNotExist fails if path exists.
   756  func (tg *testgoData) mustNotExist(path string) {
   757  	tg.t.Helper()
   758  	if _, err := os.Stat(path); err == nil || !os.IsNotExist(err) {
   759  		tg.t.Fatalf("%s exists but should not (%v)", path, err)
   760  	}
   761  }
   762  
   763  // wantExecutable fails with msg if path is not executable.
   764  func (tg *testgoData) wantExecutable(path, msg string) {
   765  	tg.t.Helper()
   766  	if st, err := os.Stat(path); err != nil {
   767  		if !os.IsNotExist(err) {
   768  			tg.t.Log(err)
   769  		}
   770  		tg.t.Fatal(msg)
   771  	} else {
   772  		if runtime.GOOS != "windows" && st.Mode()&0111 == 0 {
   773  			tg.t.Fatalf("binary %s exists but is not executable", path)
   774  		}
   775  	}
   776  }
   777  
   778  // isStale reports whether pkg is stale, and why
   779  func (tg *testgoData) isStale(pkg string) (bool, string) {
   780  	tg.t.Helper()
   781  	tg.run("list", "-f", "{{.Stale}}:{{.StaleReason}}", pkg)
   782  	v := strings.TrimSpace(tg.getStdout())
   783  	f := strings.SplitN(v, ":", 2)
   784  	if len(f) == 2 {
   785  		switch f[0] {
   786  		case "true":
   787  			return true, f[1]
   788  		case "false":
   789  			return false, f[1]
   790  		}
   791  	}
   792  	tg.t.Fatalf("unexpected output checking staleness of package %v: %v", pkg, v)
   793  	panic("unreachable")
   794  }
   795  
   796  // wantStale fails with msg if pkg is not stale.
   797  func (tg *testgoData) wantStale(pkg, reason, msg string) {
   798  	tg.t.Helper()
   799  	stale, why := tg.isStale(pkg)
   800  	if !stale {
   801  		tg.t.Fatal(msg)
   802  	}
   803  	// We always accept the reason as being "not installed but
   804  	// available in build cache", because when that is the case go
   805  	// list doesn't try to sort out the underlying reason why the
   806  	// package is not installed.
   807  	if reason == "" && why != "" || !strings.Contains(why, reason) && !strings.Contains(why, "not installed but available in build cache") {
   808  		tg.t.Errorf("wrong reason for Stale=true: %q, want %q", why, reason)
   809  	}
   810  }
   811  
   812  // wantNotStale fails with msg if pkg is stale.
   813  func (tg *testgoData) wantNotStale(pkg, reason, msg string) {
   814  	tg.t.Helper()
   815  	stale, why := tg.isStale(pkg)
   816  	if stale {
   817  		tg.t.Fatal(msg)
   818  	}
   819  	if reason == "" && why != "" || !strings.Contains(why, reason) {
   820  		tg.t.Errorf("wrong reason for Stale=false: %q, want %q", why, reason)
   821  	}
   822  }
   823  
   824  // If -testwork is specified, the test prints the name of the temp directory
   825  // and does not remove it when done, so that a programmer can
   826  // poke at the test file tree afterward.
   827  var testWork = flag.Bool("testwork", false, "")
   828  
   829  // cleanup cleans up a test that runs testgo.
   830  func (tg *testgoData) cleanup() {
   831  	tg.t.Helper()
   832  	if *testWork {
   833  		if tg.tempdir != "" {
   834  			tg.t.Logf("TESTWORK=%s\n", tg.path("."))
   835  		}
   836  		return
   837  	}
   838  	for _, path := range tg.temps {
   839  		tg.check(removeAll(path))
   840  	}
   841  	if tg.tempdir != "" {
   842  		tg.check(removeAll(tg.tempdir))
   843  	}
   844  }
   845  
   846  func removeAll(dir string) error {
   847  	// module cache has 0444 directories;
   848  	// make them writable in order to remove content.
   849  	filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error {
   850  		// chmod not only directories, but also things that we couldn't even stat
   851  		// due to permission errors: they may also be unreadable directories.
   852  		if err != nil || info.IsDir() {
   853  			os.Chmod(path, 0777)
   854  		}
   855  		return nil
   856  	})
   857  	return robustio.RemoveAll(dir)
   858  }
   859  
   860  func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
   861  	if testing.Short() {
   862  		t.Skip("skipping lengthy test in short mode")
   863  	}
   864  
   865  	tg := testgo(t)
   866  	defer tg.cleanup()
   867  	tg.parallel()
   868  
   869  	// Set GOCACHE to an empty directory so that a previous run of
   870  	// this test does not affect the staleness of the packages it builds.
   871  	tg.tempDir("gocache")
   872  	tg.setenv("GOCACHE", tg.path("gocache"))
   873  
   874  	// Copy the runtime packages into a temporary GOROOT
   875  	// so that we can change files.
   876  	var dirs []string
   877  	tg.run("list", "-deps", "runtime")
   878  	pkgs := strings.Split(strings.TrimSpace(tg.getStdout()), "\n")
   879  	for _, pkg := range pkgs {
   880  		dirs = append(dirs, filepath.Join("src", pkg))
   881  	}
   882  	dirs = append(dirs,
   883  		filepath.Join("pkg/tool", goHostOS+"_"+goHostArch),
   884  		"pkg/include",
   885  	)
   886  	for _, copydir := range dirs {
   887  		srcdir := filepath.Join(testGOROOT, copydir)
   888  		tg.tempDir(filepath.Join("goroot", copydir))
   889  		err := filepath.WalkDir(srcdir,
   890  			func(path string, info fs.DirEntry, err error) error {
   891  				if err != nil {
   892  					return err
   893  				}
   894  				if info.IsDir() {
   895  					return nil
   896  				}
   897  				srcrel, err := filepath.Rel(srcdir, path)
   898  				if err != nil {
   899  					return err
   900  				}
   901  				dest := filepath.Join("goroot", copydir, srcrel)
   902  				if _, err := os.Stat(dest); err == nil {
   903  					return nil
   904  				}
   905  				data, err := os.ReadFile(path)
   906  				if err != nil {
   907  					return err
   908  				}
   909  				tg.tempFile(dest, string(data))
   910  				if strings.Contains(copydir, filepath.Join("pkg", "tool")) {
   911  					os.Chmod(tg.path(dest), 0777)
   912  				}
   913  				return nil
   914  			})
   915  		if err != nil {
   916  			t.Fatal(err)
   917  		}
   918  	}
   919  	tg.setenv("GOROOT", tg.path("goroot"))
   920  
   921  	addVar := func(name string, idx int) (restore func()) {
   922  		data, err := os.ReadFile(name)
   923  		if err != nil {
   924  			t.Fatal(err)
   925  		}
   926  		old := data
   927  		data = append(data, fmt.Sprintf("var DummyUnusedVar%d bool\n", idx)...)
   928  		if err := os.WriteFile(name, append(data, '\n'), 0666); err != nil {
   929  			t.Fatal(err)
   930  		}
   931  		tg.sleep()
   932  		return func() {
   933  			if err := os.WriteFile(name, old, 0666); err != nil {
   934  				t.Fatal(err)
   935  			}
   936  		}
   937  	}
   938  
   939  	// Every main package depends on the "runtime".
   940  	tg.tempFile("d1/src/p1/p1.go", `package main; func main(){}`)
   941  	tg.setenv("GOPATH", tg.path("d1"))
   942  	// Pass -i flag to rebuild everything outdated.
   943  	tg.run("install", "p1")
   944  	tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, before any changes")
   945  
   946  	// Changing mtime of internal/runtime/sys/sys.go
   947  	// should have no effect: only the content matters.
   948  	// In fact this should be true even outside a release branch.
   949  	sys := tg.path("goroot/src/internal/runtime/sys/sys.go")
   950  	tg.sleep()
   951  	restore := addVar(sys, 0)
   952  	restore()
   953  	tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after updating mtime of internal/runtime/sys/sys.go")
   954  
   955  	// But changing content of any file should have an effect.
   956  	// Previously zversion.go was the only one that mattered;
   957  	// now they all matter, so keep using sys.go.
   958  	restore = addVar(sys, 1)
   959  	defer restore()
   960  	tg.wantStale("p1", "stale dependency: internal/runtime/sys", "./testgo list claims p1 is NOT stale, incorrectly, after changing sys.go")
   961  	restore()
   962  	tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after changing back to old release")
   963  	addVar(sys, 2)
   964  	tg.wantStale("p1", "stale dependency: internal/runtime/sys", "./testgo list claims p1 is NOT stale, incorrectly, after changing sys.go again")
   965  	tg.run("install", "p1")
   966  	tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with new release")
   967  
   968  	// Restore to "old" release.
   969  	restore()
   970  	tg.wantStale("p1", "not installed but available in build cache", "./testgo list claims p1 is NOT stale, incorrectly, after restoring sys.go")
   971  	tg.run("install", "p1")
   972  	tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with old release")
   973  }
   974  
   975  // Issue 4104.
   976  func TestGoTestWithPackageListedMultipleTimes(t *testing.T) {
   977  	tooSlow(t, "links and runs a test")
   978  
   979  	tg := testgo(t)
   980  	defer tg.cleanup()
   981  	tg.parallel()
   982  	tg.run("test", "errors", "errors", "errors", "errors", "errors")
   983  	if strings.Contains(strings.TrimSpace(tg.getStdout()), "\n") {
   984  		t.Error("go test errors errors errors errors errors tested the same package multiple times")
   985  	}
   986  }
   987  
   988  func TestGoListHasAConsistentOrder(t *testing.T) {
   989  	tooSlow(t, "walks all of GOROOT/src twice")
   990  
   991  	tg := testgo(t)
   992  	defer tg.cleanup()
   993  	tg.parallel()
   994  	tg.run("list", "std")
   995  	first := tg.getStdout()
   996  	tg.run("list", "std")
   997  	if first != tg.getStdout() {
   998  		t.Error("go list std ordering is inconsistent")
   999  	}
  1000  }
  1001  
  1002  func TestGoListStdDoesNotIncludeCommands(t *testing.T) {
  1003  	tooSlow(t, "walks all of GOROOT/src")
  1004  
  1005  	tg := testgo(t)
  1006  	defer tg.cleanup()
  1007  	tg.parallel()
  1008  	tg.run("list", "std")
  1009  	tg.grepStdoutNot("cmd/", "go list std shows commands")
  1010  }
  1011  
  1012  func TestGoListCmdOnlyShowsCommands(t *testing.T) {
  1013  	skipIfGccgo(t, "gccgo does not have GOROOT")
  1014  	tooSlow(t, "walks all of GOROOT/src/cmd")
  1015  
  1016  	tg := testgo(t)
  1017  	defer tg.cleanup()
  1018  	tg.parallel()
  1019  	tg.run("list", "cmd")
  1020  	out := strings.TrimSpace(tg.getStdout())
  1021  	for _, line := range strings.Split(out, "\n") {
  1022  		if !strings.Contains(line, "cmd/") {
  1023  			t.Error("go list cmd shows non-commands")
  1024  			break
  1025  		}
  1026  	}
  1027  }
  1028  
  1029  func TestGoListDeps(t *testing.T) {
  1030  	tg := testgo(t)
  1031  	defer tg.cleanup()
  1032  	tg.parallel()
  1033  	tg.tempDir("src/p1/p2/p3/p4")
  1034  	tg.setenv("GOPATH", tg.path("."))
  1035  	tg.tempFile("src/p1/p.go", "package p1\nimport _ \"p1/p2\"\n")
  1036  	tg.tempFile("src/p1/p2/p.go", "package p2\nimport _ \"p1/p2/p3\"\n")
  1037  	tg.tempFile("src/p1/p2/p3/p.go", "package p3\nimport _ \"p1/p2/p3/p4\"\n")
  1038  	tg.tempFile("src/p1/p2/p3/p4/p.go", "package p4\n")
  1039  	tg.run("list", "-f", "{{.Deps}}", "p1")
  1040  	tg.grepStdout("p1/p2/p3/p4", "Deps(p1) does not mention p4")
  1041  
  1042  	tg.run("list", "-deps", "p1")
  1043  	tg.grepStdout("p1/p2/p3/p4", "-deps p1 does not mention p4")
  1044  
  1045  	if runtime.Compiler != "gccgo" {
  1046  		// Check the list is in dependency order.
  1047  		tg.run("list", "-deps", "math")
  1048  		want := "unsafe\ninternal/cpu\nmath/bits\nmath\n"
  1049  		out := tg.stdout.String()
  1050  		if !strings.Contains(out, "internal/cpu") {
  1051  			// Some systems don't use internal/cpu.
  1052  			want = "unsafe\nmath/bits\nmath\n"
  1053  		}
  1054  		if tg.stdout.String() != want {
  1055  			t.Fatalf("list -deps math: wrong order\nhave %q\nwant %q", tg.stdout.String(), want)
  1056  		}
  1057  	}
  1058  }
  1059  
  1060  func TestGoListCompiledCgo(t *testing.T) {
  1061  	tooSlow(t, "compiles cgo files")
  1062  
  1063  	tg := testgo(t)
  1064  	defer tg.cleanup()
  1065  	tg.parallel()
  1066  	tg.makeTempdir()
  1067  	tg.setenv("GOCACHE", tg.tempdir)
  1068  
  1069  	tg.run("list", "-f", `{{join .CgoFiles "\n"}}`, "net")
  1070  	if tg.stdout.String() == "" {
  1071  		t.Skip("net does not use cgo")
  1072  	}
  1073  	if strings.Contains(tg.stdout.String(), tg.tempdir) {
  1074  		t.Fatalf(".CgoFiles unexpectedly mentioned cache %s", tg.tempdir)
  1075  	}
  1076  	tg.run("list", "-compiled", "-f", `{{.Dir}}{{"\n"}}{{join .CompiledGoFiles "\n"}}`, "net")
  1077  	if !strings.Contains(tg.stdout.String(), tg.tempdir) {
  1078  		t.Fatalf(".CompiledGoFiles with -compiled did not mention cache %s", tg.tempdir)
  1079  	}
  1080  	dir := ""
  1081  	for _, file := range strings.Split(tg.stdout.String(), "\n") {
  1082  		if file == "" {
  1083  			continue
  1084  		}
  1085  		if dir == "" {
  1086  			dir = file
  1087  			continue
  1088  		}
  1089  		if !strings.Contains(file, "/") && !strings.Contains(file, `\`) {
  1090  			file = filepath.Join(dir, file)
  1091  		}
  1092  		if _, err := os.Stat(file); err != nil {
  1093  			t.Fatalf("cannot find .CompiledGoFiles result %s: %v", file, err)
  1094  		}
  1095  	}
  1096  }
  1097  
  1098  func TestGoListExport(t *testing.T) {
  1099  	tooSlow(t, "runs build for -export")
  1100  
  1101  	skipIfGccgo(t, "gccgo does not have standard packages")
  1102  	tg := testgo(t)
  1103  	defer tg.cleanup()
  1104  	tg.parallel()
  1105  	tg.makeTempdir()
  1106  	tg.setenv("GOCACHE", tg.tempdir)
  1107  
  1108  	tg.run("list", "-f", "{{.Export}}", "strings")
  1109  	if tg.stdout.String() != "" {
  1110  		t.Fatalf(".Export without -export unexpectedly set")
  1111  	}
  1112  	tg.run("list", "-export", "-f", "{{.Export}}", "strings")
  1113  	file := strings.TrimSpace(tg.stdout.String())
  1114  	if file == "" {
  1115  		t.Fatalf(".Export with -export was empty")
  1116  	}
  1117  	if _, err := os.Stat(file); err != nil {
  1118  		t.Fatalf("cannot find .Export result %s: %v", file, err)
  1119  	}
  1120  
  1121  	tg.run("list", "-export", "-f", "{{.BuildID}}", "strings")
  1122  	buildID := strings.TrimSpace(tg.stdout.String())
  1123  	if buildID == "" {
  1124  		t.Fatalf(".BuildID with -export was empty")
  1125  	}
  1126  
  1127  	tg.run("tool", "buildid", file)
  1128  	toolBuildID := strings.TrimSpace(tg.stdout.String())
  1129  	if buildID != toolBuildID {
  1130  		t.Fatalf(".BuildID with -export %q disagrees with 'go tool buildid' %q", buildID, toolBuildID)
  1131  	}
  1132  }
  1133  
  1134  // Issue 4096. Validate the output of unsuccessful go install foo/quxx.
  1135  func TestUnsuccessfulGoInstallShouldMentionMissingPackage(t *testing.T) {
  1136  	tg := testgo(t)
  1137  	defer tg.cleanup()
  1138  	tg.parallel()
  1139  	tg.runFail("install", "foo/quxx")
  1140  	if tg.grepCountBoth(`cannot find package "foo/quxx" in any of`) != 1 {
  1141  		t.Error(`go install foo/quxx expected error: .*cannot find package "foo/quxx" in any of`)
  1142  	}
  1143  }
  1144  
  1145  func TestGOROOTSearchFailureReporting(t *testing.T) {
  1146  	tg := testgo(t)
  1147  	defer tg.cleanup()
  1148  	tg.parallel()
  1149  	tg.runFail("install", "foo/quxx")
  1150  	if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("foo", "quxx"))+` \(from \$GOROOT\)$`) != 1 {
  1151  		t.Error(`go install foo/quxx expected error: .*foo/quxx (from $GOROOT)`)
  1152  	}
  1153  }
  1154  
  1155  func TestMultipleGOPATHEntriesReportedSeparately(t *testing.T) {
  1156  	tg := testgo(t)
  1157  	defer tg.cleanup()
  1158  	tg.parallel()
  1159  	sep := string(filepath.ListSeparator)
  1160  	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
  1161  	tg.runFail("install", "foo/quxx")
  1162  	if tg.grepCountBoth(`testdata[/\\].[/\\]src[/\\]foo[/\\]quxx`) != 2 {
  1163  		t.Error(`go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)\n.*testdata/b/src/foo/quxx`)
  1164  	}
  1165  }
  1166  
  1167  // Test (from $GOPATH) annotation is reported for the first GOPATH entry,
  1168  func TestMentionGOPATHInFirstGOPATHEntry(t *testing.T) {
  1169  	tg := testgo(t)
  1170  	defer tg.cleanup()
  1171  	tg.parallel()
  1172  	sep := string(filepath.ListSeparator)
  1173  	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
  1174  	tg.runFail("install", "foo/quxx")
  1175  	if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("testdata", "a", "src", "foo", "quxx"))+` \(from \$GOPATH\)$`) != 1 {
  1176  		t.Error(`go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)`)
  1177  	}
  1178  }
  1179  
  1180  // but not on the second.
  1181  func TestMentionGOPATHNotOnSecondEntry(t *testing.T) {
  1182  	tg := testgo(t)
  1183  	defer tg.cleanup()
  1184  	tg.parallel()
  1185  	sep := string(filepath.ListSeparator)
  1186  	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
  1187  	tg.runFail("install", "foo/quxx")
  1188  	if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("testdata", "b", "src", "foo", "quxx"))+`$`) != 1 {
  1189  		t.Error(`go install foo/quxx expected error: .*testdata/b/src/foo/quxx`)
  1190  	}
  1191  }
  1192  
  1193  func homeEnvName() string {
  1194  	switch runtime.GOOS {
  1195  	case "windows":
  1196  		return "USERPROFILE"
  1197  	case "plan9":
  1198  		return "home"
  1199  	default:
  1200  		return "HOME"
  1201  	}
  1202  }
  1203  
  1204  func tempEnvName() string {
  1205  	switch runtime.GOOS {
  1206  	case "windows":
  1207  		return "TMP"
  1208  	case "plan9":
  1209  		return "TMPDIR" // actually plan 9 doesn't have one at all but this is fine
  1210  	default:
  1211  		return "TMPDIR"
  1212  	}
  1213  }
  1214  
  1215  func pathEnvName() string {
  1216  	switch runtime.GOOS {
  1217  	case "plan9":
  1218  		return "path"
  1219  	default:
  1220  		return "PATH"
  1221  	}
  1222  }
  1223  
  1224  func TestDefaultGOPATH(t *testing.T) {
  1225  	tg := testgo(t)
  1226  	defer tg.cleanup()
  1227  	tg.parallel()
  1228  	tg.tempDir("home/go")
  1229  	tg.setenv(homeEnvName(), tg.path("home"))
  1230  	// Set TEST_TELEMETRY_DIR to a path that doesn't exist
  1231  	// so that the counter uploading code doesn't write
  1232  	// the counter token file to the temp dir after the test finishes.
  1233  	tg.setenv("TEST_TELEMETRY_DIR", "/no-telemetry-dir")
  1234  
  1235  	tg.run("env", "GOPATH")
  1236  	tg.grepStdout(regexp.QuoteMeta(tg.path("home/go")), "want GOPATH=$HOME/go")
  1237  
  1238  	tg.setenv("GOROOT", tg.path("home/go"))
  1239  	tg.run("env", "GOPATH")
  1240  	tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go")
  1241  
  1242  	tg.setenv("GOROOT", tg.path("home/go")+"/")
  1243  	tg.run("env", "GOPATH")
  1244  	tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go/")
  1245  }
  1246  
  1247  func TestDefaultGOPATHPrintedSearchList(t *testing.T) {
  1248  	tg := testgo(t)
  1249  	defer tg.cleanup()
  1250  	tg.parallel()
  1251  	tg.setenv("GOPATH", "")
  1252  	tg.tempDir("home")
  1253  	tg.setenv(homeEnvName(), tg.path("home"))
  1254  	// Set TEST_TELEMETRY_DIR to a path that doesn't exist
  1255  	// so that the counter uploading code doesn't write
  1256  	// the counter token file to the temp dir after the test finishes.
  1257  	tg.setenv("TEST_TELEMETRY_DIR", "/no-telemetry-dir")
  1258  
  1259  	tg.runFail("install", "github.com/golang/example/hello")
  1260  	tg.grepStderr(regexp.QuoteMeta(tg.path("home/go/src/github.com/golang/example/hello"))+`.*from \$GOPATH`, "expected default GOPATH")
  1261  }
  1262  
  1263  func TestLdflagsArgumentsWithSpacesIssue3941(t *testing.T) {
  1264  	skipIfGccgo(t, "gccgo does not support -ldflags -X")
  1265  	tooSlow(t, "compiles and links a binary")
  1266  
  1267  	tg := testgo(t)
  1268  	defer tg.cleanup()
  1269  	tg.parallel()
  1270  	tg.tempFile("main.go", `package main
  1271  		var extern string
  1272  		func main() {
  1273  			println(extern)
  1274  		}`)
  1275  	tg.run("run", "-ldflags", `-X "main.extern=hello world"`, tg.path("main.go"))
  1276  	tg.grepStderr("^hello world", `ldflags -X "main.extern=hello world"' failed`)
  1277  }
  1278  
  1279  func TestLdFlagsLongArgumentsIssue42295(t *testing.T) {
  1280  	// Test the extremely long command line arguments that contain '\n' characters
  1281  	// get encoded and passed correctly.
  1282  	skipIfGccgo(t, "gccgo does not support -ldflags -X")
  1283  	tooSlow(t, "compiles and links a binary")
  1284  
  1285  	tg := testgo(t)
  1286  	defer tg.cleanup()
  1287  	tg.parallel()
  1288  	tg.tempFile("main.go", `package main
  1289  		var extern string
  1290  		func main() {
  1291  			print(extern)
  1292  		}`)
  1293  	testStr := "test test test test test \n\\ "
  1294  	var buf strings.Builder
  1295  	for buf.Len() < sys.ExecArgLengthLimit+1 {
  1296  		buf.WriteString(testStr)
  1297  	}
  1298  	tg.run("run", "-ldflags", fmt.Sprintf(`-X "main.extern=%s"`, buf.String()), tg.path("main.go"))
  1299  	if tg.stderr.String() != buf.String() {
  1300  		t.Errorf("strings differ")
  1301  	}
  1302  }
  1303  
  1304  func TestGoTestDashCDashOControlsBinaryLocation(t *testing.T) {
  1305  	skipIfGccgo(t, "gccgo has no standard packages")
  1306  	tooSlow(t, "compiles and links a test binary")
  1307  
  1308  	tg := testgo(t)
  1309  	defer tg.cleanup()
  1310  	tg.parallel()
  1311  	tg.makeTempdir()
  1312  	tg.run("test", "-c", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
  1313  	tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -c -o myerrors.test did not create myerrors.test")
  1314  }
  1315  
  1316  func TestGoTestDashOWritesBinary(t *testing.T) {
  1317  	skipIfGccgo(t, "gccgo has no standard packages")
  1318  	tooSlow(t, "compiles and runs a test binary")
  1319  
  1320  	tg := testgo(t)
  1321  	defer tg.cleanup()
  1322  	tg.parallel()
  1323  	tg.makeTempdir()
  1324  	tg.run("test", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
  1325  	tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -o myerrors.test did not create myerrors.test")
  1326  }
  1327  
  1328  // Issue 4515.
  1329  func TestInstallWithTags(t *testing.T) {
  1330  	tooSlow(t, "compiles and links binaries")
  1331  
  1332  	tg := testgo(t)
  1333  	defer tg.cleanup()
  1334  	tg.parallel()
  1335  	tg.tempDir("bin")
  1336  	tg.tempFile("src/example/a/main.go", `package main
  1337  		func main() {}`)
  1338  	tg.tempFile("src/example/b/main.go", `// +build mytag
  1339  
  1340  		package main
  1341  		func main() {}`)
  1342  	tg.setenv("GOPATH", tg.path("."))
  1343  	tg.run("install", "-tags", "mytag", "example/a", "example/b")
  1344  	tg.wantExecutable(tg.path("bin/a"+exeSuffix), "go install example/a example/b did not install binaries")
  1345  	tg.wantExecutable(tg.path("bin/b"+exeSuffix), "go install example/a example/b did not install binaries")
  1346  	tg.must(os.Remove(tg.path("bin/a" + exeSuffix)))
  1347  	tg.must(os.Remove(tg.path("bin/b" + exeSuffix)))
  1348  	tg.run("install", "-tags", "mytag", "example/...")
  1349  	tg.wantExecutable(tg.path("bin/a"+exeSuffix), "go install example/... did not install binaries")
  1350  	tg.wantExecutable(tg.path("bin/b"+exeSuffix), "go install example/... did not install binaries")
  1351  	tg.run("list", "-tags", "mytag", "example/b...")
  1352  	if strings.TrimSpace(tg.getStdout()) != "example/b" {
  1353  		t.Error("go list example/b did not find example/b")
  1354  	}
  1355  }
  1356  
  1357  // Issue 17451, 17662.
  1358  func TestSymlinkWarning(t *testing.T) {
  1359  	tg := testgo(t)
  1360  	defer tg.cleanup()
  1361  	tg.parallel()
  1362  	tg.makeTempdir()
  1363  	tg.setenv("GOPATH", tg.path("."))
  1364  
  1365  	tg.tempDir("src/example/xx")
  1366  	tg.tempDir("yy/zz")
  1367  	tg.tempFile("yy/zz/zz.go", "package zz\n")
  1368  	if err := os.Symlink(tg.path("yy"), tg.path("src/example/xx/yy")); err != nil {
  1369  		t.Skipf("symlink failed: %v", err)
  1370  	}
  1371  	tg.run("list", "example/xx/z...")
  1372  	tg.grepStdoutNot(".", "list should not have matched anything")
  1373  	tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages")
  1374  	tg.grepStderrNot("symlink", "list should not have reported symlink")
  1375  
  1376  	tg.run("list", "example/xx/...")
  1377  	tg.grepStdoutNot(".", "list should not have matched anything")
  1378  	tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages")
  1379  	tg.grepStderr("ignoring symlink", "list should have reported symlink")
  1380  }
  1381  
  1382  func TestCgoShowsFullPathNames(t *testing.T) {
  1383  	testenv.MustHaveCGO(t)
  1384  
  1385  	tg := testgo(t)
  1386  	defer tg.cleanup()
  1387  	tg.parallel()
  1388  	tg.tempFile("src/x/y/dirname/foo.go", `
  1389  		package foo
  1390  		import "C"
  1391  		func f() {`)
  1392  	tg.setenv("GOPATH", tg.path("."))
  1393  	tg.runFail("build", "x/y/dirname")
  1394  	tg.grepBoth("x/y/dirname", "error did not use full path")
  1395  }
  1396  
  1397  func TestCgoHandlesWlORIGIN(t *testing.T) {
  1398  	tooSlow(t, "compiles cgo files")
  1399  	testenv.MustHaveCGO(t)
  1400  
  1401  	tg := testgo(t)
  1402  	defer tg.cleanup()
  1403  	tg.parallel()
  1404  	tg.tempFile("src/origin/origin.go", `package origin
  1405  		// #cgo !darwin,!windows LDFLAGS: -Wl,-rpath,$ORIGIN
  1406  		// void f(void) {}
  1407  		import "C"
  1408  		func f() { C.f() }`)
  1409  	tg.setenv("GOPATH", tg.path("."))
  1410  	tg.run("build", "origin")
  1411  }
  1412  
  1413  func TestCgoPkgConfig(t *testing.T) {
  1414  	tooSlow(t, "compiles cgo files")
  1415  	testenv.MustHaveCGO(t)
  1416  
  1417  	tg := testgo(t)
  1418  	defer tg.cleanup()
  1419  	tg.parallel()
  1420  
  1421  	tg.run("env", "PKG_CONFIG")
  1422  	pkgConfig := strings.TrimSpace(tg.getStdout())
  1423  	testenv.MustHaveExecPath(t, pkgConfig)
  1424  	if out, err := testenv.Command(t, pkgConfig, "--atleast-pkgconfig-version", "0.24").CombinedOutput(); err != nil {
  1425  		t.Skipf("%s --atleast-pkgconfig-version 0.24: %v\n%s", pkgConfig, err, out)
  1426  	}
  1427  
  1428  	// OpenBSD's pkg-config is strict about whitespace and only
  1429  	// supports backslash-escaped whitespace. It does not support
  1430  	// quotes, which the normal freedesktop.org pkg-config does
  1431  	// support. See https://man.openbsd.org/pkg-config.1
  1432  	tg.tempFile("foo.pc", `
  1433  Name: foo
  1434  Description: The foo library
  1435  Version: 1.0.0
  1436  Cflags: -Dhello=10 -Dworld=+32 -DDEFINED_FROM_PKG_CONFIG=hello\ world
  1437  `)
  1438  	tg.tempFile("foo.go", `package main
  1439  
  1440  /*
  1441  #cgo pkg-config: foo
  1442  int value() {
  1443  	return DEFINED_FROM_PKG_CONFIG;
  1444  }
  1445  */
  1446  import "C"
  1447  import "os"
  1448  
  1449  func main() {
  1450  	if C.value() != 42 {
  1451  		println("value() =", C.value(), "wanted 42")
  1452  		os.Exit(1)
  1453  	}
  1454  }
  1455  `)
  1456  	tg.setenv("PKG_CONFIG_PATH", tg.path("."))
  1457  	tg.run("run", tg.path("foo.go"))
  1458  
  1459  	libs := `Libs: -Wl,-rpath=/path\ with\ spaces/bin`
  1460  	if runtime.GOOS == "darwin" {
  1461  		libs = "" // darwin linker doesn't have -rpath
  1462  	}
  1463  	// test for ldflags
  1464  	tg.tempFile("bar.pc", `
  1465  Name: bar
  1466  Description: The bar library
  1467  Version: 1.0.0
  1468  `+libs+`
  1469  `)
  1470  
  1471  	tg.tempFile("bar.go", `package main
  1472  /*
  1473  #cgo pkg-config: bar
  1474  */
  1475  import "C"
  1476  func main() {}
  1477  `)
  1478  	tg.run("run", tg.path("bar.go"))
  1479  }
  1480  
  1481  // Test that you cannot use a local import in a package
  1482  // accessed by a non-local import (found in a GOPATH/GOROOT).
  1483  // See golang.org/issue/17475.
  1484  func TestImportLocal(t *testing.T) {
  1485  	tooSlow(t, "builds a lot of sequential packages")
  1486  
  1487  	tg := testgo(t)
  1488  	tg.parallel()
  1489  	defer tg.cleanup()
  1490  
  1491  	tg.tempFile("src/dir/x/x.go", `package x
  1492  		var X int
  1493  	`)
  1494  	tg.setenv("GOPATH", tg.path("."))
  1495  	tg.run("build", "dir/x")
  1496  
  1497  	// Ordinary import should work.
  1498  	tg.tempFile("src/dir/p0/p.go", `package p0
  1499  		import "dir/x"
  1500  		var _ = x.X
  1501  	`)
  1502  	tg.run("build", "dir/p0")
  1503  
  1504  	// Relative import should not.
  1505  	tg.tempFile("src/dir/p1/p.go", `package p1
  1506  		import "../x"
  1507  		var _ = x.X
  1508  	`)
  1509  	tg.runFail("build", "dir/p1")
  1510  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1511  
  1512  	// ... even in a test.
  1513  	tg.tempFile("src/dir/p2/p.go", `package p2
  1514  	`)
  1515  	tg.tempFile("src/dir/p2/p_test.go", `package p2
  1516  		import "../x"
  1517  		import "testing"
  1518  		var _ = x.X
  1519  		func TestFoo(t *testing.T) {}
  1520  	`)
  1521  	tg.run("build", "dir/p2")
  1522  	tg.runFail("test", "dir/p2")
  1523  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1524  
  1525  	// ... even in an xtest.
  1526  	tg.tempFile("src/dir/p2/p_test.go", `package p2_test
  1527  		import "../x"
  1528  		import "testing"
  1529  		var _ = x.X
  1530  		func TestFoo(t *testing.T) {}
  1531  	`)
  1532  	tg.run("build", "dir/p2")
  1533  	tg.runFail("test", "dir/p2")
  1534  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1535  
  1536  	// Relative import starting with ./ should not work either.
  1537  	tg.tempFile("src/dir/d.go", `package dir
  1538  		import "./x"
  1539  		var _ = x.X
  1540  	`)
  1541  	tg.runFail("build", "dir")
  1542  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1543  
  1544  	// ... even in a test.
  1545  	tg.tempFile("src/dir/d.go", `package dir
  1546  	`)
  1547  	tg.tempFile("src/dir/d_test.go", `package dir
  1548  		import "./x"
  1549  		import "testing"
  1550  		var _ = x.X
  1551  		func TestFoo(t *testing.T) {}
  1552  	`)
  1553  	tg.run("build", "dir")
  1554  	tg.runFail("test", "dir")
  1555  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1556  
  1557  	// ... even in an xtest.
  1558  	tg.tempFile("src/dir/d_test.go", `package dir_test
  1559  		import "./x"
  1560  		import "testing"
  1561  		var _ = x.X
  1562  		func TestFoo(t *testing.T) {}
  1563  	`)
  1564  	tg.run("build", "dir")
  1565  	tg.runFail("test", "dir")
  1566  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1567  
  1568  	// Relative import plain ".." should not work.
  1569  	tg.tempFile("src/dir/x/y/y.go", `package dir
  1570  		import ".."
  1571  		var _ = x.X
  1572  	`)
  1573  	tg.runFail("build", "dir/x/y")
  1574  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1575  
  1576  	// ... even in a test.
  1577  	tg.tempFile("src/dir/x/y/y.go", `package y
  1578  	`)
  1579  	tg.tempFile("src/dir/x/y/y_test.go", `package y
  1580  		import ".."
  1581  		import "testing"
  1582  		var _ = x.X
  1583  		func TestFoo(t *testing.T) {}
  1584  	`)
  1585  	tg.run("build", "dir/x/y")
  1586  	tg.runFail("test", "dir/x/y")
  1587  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1588  
  1589  	// ... even in an x test.
  1590  	tg.tempFile("src/dir/x/y/y_test.go", `package y_test
  1591  		import ".."
  1592  		import "testing"
  1593  		var _ = x.X
  1594  		func TestFoo(t *testing.T) {}
  1595  	`)
  1596  	tg.run("build", "dir/x/y")
  1597  	tg.runFail("test", "dir/x/y")
  1598  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1599  
  1600  	// Relative import "." should not work.
  1601  	tg.tempFile("src/dir/x/xx.go", `package x
  1602  		import "."
  1603  		var _ = x.X
  1604  	`)
  1605  	tg.runFail("build", "dir/x")
  1606  	tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
  1607  
  1608  	// ... even in a test.
  1609  	tg.tempFile("src/dir/x/xx.go", `package x
  1610  	`)
  1611  	tg.tempFile("src/dir/x/xx_test.go", `package x
  1612  		import "."
  1613  		import "testing"
  1614  		var _ = x.X
  1615  		func TestFoo(t *testing.T) {}
  1616  	`)
  1617  	tg.run("build", "dir/x")
  1618  	tg.runFail("test", "dir/x")
  1619  	tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
  1620  
  1621  	// ... even in an xtest.
  1622  	tg.tempFile("src/dir/x/xx.go", `package x
  1623  	`)
  1624  	tg.tempFile("src/dir/x/xx_test.go", `package x_test
  1625  		import "."
  1626  		import "testing"
  1627  		var _ = x.X
  1628  		func TestFoo(t *testing.T) {}
  1629  	`)
  1630  	tg.run("build", "dir/x")
  1631  	tg.runFail("test", "dir/x")
  1632  	tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
  1633  }
  1634  
  1635  func TestGoInstallPkgdir(t *testing.T) {
  1636  	skipIfGccgo(t, "gccgo has no standard packages")
  1637  	tooSlow(t, "builds a package with cgo dependencies")
  1638  	// Only the stdlib packages that use cgo have install
  1639  	// targets, (we're using net below) so cgo is required
  1640  	// for the install.
  1641  	testenv.MustHaveCGO(t)
  1642  
  1643  	tg := testgo(t)
  1644  	tg.parallel()
  1645  	tg.setenv("GODEBUG", "installgoroot=all")
  1646  	defer tg.cleanup()
  1647  	tg.makeTempdir()
  1648  	pkg := tg.path(".")
  1649  	tg.run("install", "-pkgdir", pkg, "net")
  1650  	tg.mustExist(filepath.Join(pkg, "net.a"))
  1651  	tg.mustNotExist(filepath.Join(pkg, "runtime/cgo.a"))
  1652  }
  1653  
  1654  // For issue 14337.
  1655  func TestParallelTest(t *testing.T) {
  1656  	tooSlow(t, "links and runs test binaries")
  1657  
  1658  	tg := testgo(t)
  1659  	tg.parallel()
  1660  	defer tg.cleanup()
  1661  	tg.makeTempdir()
  1662  	const testSrc = `package package_test
  1663  		import (
  1664  			"testing"
  1665  		)
  1666  		func TestTest(t *testing.T) {
  1667  		}`
  1668  	tg.tempFile("src/p1/p1_test.go", strings.Replace(testSrc, "package_test", "p1_test", 1))
  1669  	tg.tempFile("src/p2/p2_test.go", strings.Replace(testSrc, "package_test", "p2_test", 1))
  1670  	tg.tempFile("src/p3/p3_test.go", strings.Replace(testSrc, "package_test", "p3_test", 1))
  1671  	tg.tempFile("src/p4/p4_test.go", strings.Replace(testSrc, "package_test", "p4_test", 1))
  1672  	tg.setenv("GOPATH", tg.path("."))
  1673  	tg.run("test", "-p=4", "p1", "p2", "p3", "p4")
  1674  }
  1675  
  1676  func TestBinaryOnlyPackages(t *testing.T) {
  1677  	tooSlow(t, "compiles several packages sequentially")
  1678  
  1679  	tg := testgo(t)
  1680  	defer tg.cleanup()
  1681  	tg.parallel()
  1682  	tg.makeTempdir()
  1683  	tg.setenv("GOPATH", tg.path("."))
  1684  
  1685  	tg.tempFile("src/p1/p1.go", `//go:binary-only-package
  1686  
  1687  		package p1
  1688  	`)
  1689  	tg.wantStale("p1", "binary-only packages are no longer supported", "p1 is binary-only, and this message should always be printed")
  1690  	tg.runFail("install", "p1")
  1691  	tg.grepStderr("binary-only packages are no longer supported", "did not report attempt to compile binary-only package")
  1692  
  1693  	tg.tempFile("src/p1/p1.go", `
  1694  		package p1
  1695  		import "fmt"
  1696  		func F(b bool) { fmt.Printf("hello from p1\n"); if b { F(false) } }
  1697  	`)
  1698  	tg.run("install", "p1")
  1699  	os.Remove(tg.path("src/p1/p1.go"))
  1700  	tg.mustNotExist(tg.path("src/p1/p1.go"))
  1701  
  1702  	tg.tempFile("src/p2/p2.go", `//go:binary-only-packages-are-not-great
  1703  
  1704  		package p2
  1705  		import "p1"
  1706  		func F() { p1.F(true) }
  1707  	`)
  1708  	tg.runFail("install", "p2")
  1709  	tg.grepStderr("no Go files", "did not complain about missing sources")
  1710  
  1711  	tg.tempFile("src/p1/missing.go", `//go:binary-only-package
  1712  
  1713  		package p1
  1714  		import _ "fmt"
  1715  		func G()
  1716  	`)
  1717  	tg.wantStale("p1", "binary-only package", "should NOT want to rebuild p1 (first)")
  1718  	tg.runFail("install", "p2")
  1719  	tg.grepStderr("p1: binary-only packages are no longer supported", "did not report error for binary-only p1")
  1720  
  1721  	tg.run("list", "-deps", "-f", "{{.ImportPath}}: {{.BinaryOnly}}", "p2")
  1722  	tg.grepStdout("p1: true", "p1 not listed as BinaryOnly")
  1723  	tg.grepStdout("p2: false", "p2 listed as BinaryOnly")
  1724  }
  1725  
  1726  // Issue 16050 and 21884.
  1727  func TestLinkSysoFiles(t *testing.T) {
  1728  	if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
  1729  		t.Skip("not linux/amd64")
  1730  	}
  1731  
  1732  	tg := testgo(t)
  1733  	defer tg.cleanup()
  1734  	tg.parallel()
  1735  	tg.tempDir("src/syso")
  1736  	tg.tempFile("src/syso/a.syso", ``)
  1737  	tg.tempFile("src/syso/b.go", `package syso`)
  1738  	tg.setenv("GOPATH", tg.path("."))
  1739  
  1740  	// We should see the .syso file regardless of the setting of
  1741  	// CGO_ENABLED.
  1742  
  1743  	tg.setenv("CGO_ENABLED", "1")
  1744  	tg.run("list", "-f", "{{.SysoFiles}}", "syso")
  1745  	tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=1")
  1746  
  1747  	tg.setenv("CGO_ENABLED", "0")
  1748  	tg.run("list", "-f", "{{.SysoFiles}}", "syso")
  1749  	tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=0")
  1750  
  1751  	tg.setenv("CGO_ENABLED", "1")
  1752  	tg.run("list", "-msan", "-f", "{{.SysoFiles}}", "syso")
  1753  	tg.grepStdoutNot("a.syso", "unexpected syso file with -msan")
  1754  }
  1755  
  1756  // Issue 16120.
  1757  func TestGenerateUsesBuildContext(t *testing.T) {
  1758  	if runtime.GOOS == "windows" {
  1759  		t.Skip("this test won't run under Windows")
  1760  	}
  1761  
  1762  	tg := testgo(t)
  1763  	defer tg.cleanup()
  1764  	tg.parallel()
  1765  	tg.tempDir("src/gen")
  1766  	tg.tempFile("src/gen/gen.go", "package gen\n//go:generate echo $GOOS $GOARCH\n")
  1767  	tg.setenv("GOPATH", tg.path("."))
  1768  
  1769  	tg.setenv("GOOS", "linux")
  1770  	tg.setenv("GOARCH", "amd64")
  1771  	tg.run("generate", "gen")
  1772  	tg.grepStdout("linux amd64", "unexpected GOOS/GOARCH combination")
  1773  
  1774  	tg.setenv("GOOS", "darwin")
  1775  	tg.setenv("GOARCH", "arm64")
  1776  	tg.run("generate", "gen")
  1777  	tg.grepStdout("darwin arm64", "unexpected GOOS/GOARCH combination")
  1778  }
  1779  
  1780  func TestGoEnv(t *testing.T) {
  1781  	tg := testgo(t)
  1782  	tg.parallel()
  1783  	defer tg.cleanup()
  1784  	tg.setenv("GOOS", "freebsd") // to avoid invalid pair errors
  1785  	tg.setenv("GOARCH", "arm")
  1786  	tg.run("env", "GOARCH")
  1787  	tg.grepStdout("^arm$", "GOARCH not honored")
  1788  
  1789  	tg.run("env", "GCCGO")
  1790  	tg.grepStdout(".", "GCCGO unexpectedly empty")
  1791  
  1792  	tg.run("env", "CGO_CFLAGS")
  1793  	tg.grepStdout(".", "default CGO_CFLAGS unexpectedly empty")
  1794  
  1795  	tg.setenv("CGO_CFLAGS", "-foobar")
  1796  	tg.run("env", "CGO_CFLAGS")
  1797  	tg.grepStdout("^-foobar$", "CGO_CFLAGS not honored")
  1798  
  1799  	tg.setenv("CC", "gcc -fmust -fgo -ffaster")
  1800  	tg.run("env", "CC")
  1801  	tg.grepStdout("gcc", "CC not found")
  1802  	tg.run("env", "GOGCCFLAGS")
  1803  	tg.grepStdout("-ffaster", "CC arguments not found")
  1804  
  1805  	tg.run("env", "GOVERSION")
  1806  	envVersion := strings.TrimSpace(tg.stdout.String())
  1807  
  1808  	tg.run("version")
  1809  	cmdVersion := strings.TrimSpace(tg.stdout.String())
  1810  
  1811  	// If 'go version' is "go version <version> <goos>/<goarch>", then
  1812  	// 'go env GOVERSION' is just "<version>".
  1813  	if cmdVersion == envVersion || !strings.Contains(cmdVersion, envVersion) {
  1814  		t.Fatalf("'go env GOVERSION' %q should be a shorter substring of 'go version' %q", envVersion, cmdVersion)
  1815  	}
  1816  }
  1817  
  1818  const (
  1819  	noMatchesPattern = `(?m)^ok.*\[no tests to run\]`
  1820  	okPattern        = `(?m)^ok`
  1821  )
  1822  
  1823  // Issue 18044.
  1824  func TestLdBindNow(t *testing.T) {
  1825  	tg := testgo(t)
  1826  	defer tg.cleanup()
  1827  	tg.parallel()
  1828  	tg.setenv("LD_BIND_NOW", "1")
  1829  	tg.run("help")
  1830  }
  1831  
  1832  // Issue 18225.
  1833  // This is really a cmd/asm issue but this is a convenient place to test it.
  1834  func TestConcurrentAsm(t *testing.T) {
  1835  	skipIfGccgo(t, "gccgo does not use cmd/asm")
  1836  	tg := testgo(t)
  1837  	defer tg.cleanup()
  1838  	tg.parallel()
  1839  	asm := `DATA ·constants<>+0x0(SB)/8,$0
  1840  GLOBL ·constants<>(SB),8,$8
  1841  `
  1842  	tg.tempFile("go/src/p/a.s", asm)
  1843  	tg.tempFile("go/src/p/b.s", asm)
  1844  	tg.tempFile("go/src/p/p.go", `package p`)
  1845  	tg.setenv("GOPATH", tg.path("go"))
  1846  	tg.run("build", "p")
  1847  }
  1848  
  1849  // Issue 18975.
  1850  func TestFFLAGS(t *testing.T) {
  1851  	testenv.MustHaveCGO(t)
  1852  
  1853  	tg := testgo(t)
  1854  	defer tg.cleanup()
  1855  	tg.parallel()
  1856  
  1857  	tg.tempFile("p/src/p/main.go", `package main
  1858  		// #cgo FFLAGS: -no-such-fortran-flag
  1859  		import "C"
  1860  		func main() {}
  1861  	`)
  1862  	tg.tempFile("p/src/p/a.f", `! comment`)
  1863  	tg.setenv("GOPATH", tg.path("p"))
  1864  
  1865  	// This should normally fail because we are passing an unknown flag,
  1866  	// but issue #19080 points to Fortran compilers that succeed anyhow.
  1867  	// To work either way we call doRun directly rather than run or runFail.
  1868  	tg.doRun([]string{"build", "-x", "p"})
  1869  
  1870  	tg.grepStderr("no-such-fortran-flag", `missing expected "-no-such-fortran-flag"`)
  1871  }
  1872  
  1873  // Issue 19198.
  1874  // This is really a cmd/link issue but this is a convenient place to test it.
  1875  func TestDuplicateGlobalAsmSymbols(t *testing.T) {
  1876  	skipIfGccgo(t, "gccgo does not use cmd/asm")
  1877  	tooSlow(t, "links a binary with cgo dependencies")
  1878  	if runtime.GOARCH != "386" && runtime.GOARCH != "amd64" {
  1879  		t.Skipf("skipping test on %s", runtime.GOARCH)
  1880  	}
  1881  	testenv.MustHaveCGO(t)
  1882  
  1883  	tg := testgo(t)
  1884  	defer tg.cleanup()
  1885  	tg.parallel()
  1886  
  1887  	asm := `
  1888  #include "textflag.h"
  1889  
  1890  DATA sym<>+0x0(SB)/8,$0
  1891  GLOBL sym<>(SB),(NOPTR+RODATA),$8
  1892  
  1893  TEXT ·Data(SB),NOSPLIT,$0
  1894  	MOVB sym<>(SB), AX
  1895  	MOVB AX, ret+0(FP)
  1896  	RET
  1897  `
  1898  	tg.tempFile("go/src/a/a.s", asm)
  1899  	tg.tempFile("go/src/a/a.go", `package a; func Data() uint8`)
  1900  	tg.tempFile("go/src/b/b.s", asm)
  1901  	tg.tempFile("go/src/b/b.go", `package b; func Data() uint8`)
  1902  	tg.tempFile("go/src/p/p.go", `
  1903  package main
  1904  import "a"
  1905  import "b"
  1906  import "C"
  1907  func main() {
  1908  	_ = a.Data() + b.Data()
  1909  }
  1910  `)
  1911  	tg.setenv("GOPATH", tg.path("go"))
  1912  	exe := tg.path("p.exe")
  1913  	tg.creatingTemp(exe)
  1914  	tg.run("build", "-o", exe, "p")
  1915  }
  1916  
  1917  func copyFile(src, dst string, perm fs.FileMode) error {
  1918  	sf, err := os.Open(src)
  1919  	if err != nil {
  1920  		return err
  1921  	}
  1922  	defer sf.Close()
  1923  
  1924  	df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
  1925  	if err != nil {
  1926  		return err
  1927  	}
  1928  
  1929  	_, err = io.Copy(df, sf)
  1930  	err2 := df.Close()
  1931  	if err != nil {
  1932  		return err
  1933  	}
  1934  	return err2
  1935  }
  1936  
  1937  func TestNeedVersion(t *testing.T) {
  1938  	skipIfGccgo(t, "gccgo does not use cmd/compile")
  1939  	tg := testgo(t)
  1940  	defer tg.cleanup()
  1941  	tg.parallel()
  1942  	tg.tempFile("goversion.go", `package main; func main() {}`)
  1943  	path := tg.path("goversion.go")
  1944  	tg.setenv("TESTGO_TOOLCHAIN_VERSION", "go1.testgo")
  1945  	tg.runFail("run", path)
  1946  	tg.grepStderr("compile", "does not match go tool version")
  1947  }
  1948  
  1949  func TestBuildmodePIE(t *testing.T) {
  1950  	tooSlow(t, "links binaries")
  1951  
  1952  	if !platform.BuildModeSupported(runtime.Compiler, "pie", runtime.GOOS, runtime.GOARCH) {
  1953  		t.Skipf("skipping test because buildmode=pie is not supported on %s/%s", runtime.GOOS, runtime.GOARCH)
  1954  	}
  1955  	// Skip on alpine until https://go.dev/issues/54354 resolved.
  1956  	if strings.HasSuffix(testenv.Builder(), "-alpine") {
  1957  		t.Skip("skipping PIE tests on alpine; see https://go.dev/issues/54354")
  1958  	}
  1959  	t.Run("non-cgo", func(t *testing.T) {
  1960  		testBuildmodePIE(t, false, true)
  1961  	})
  1962  	t.Run("cgo", func(t *testing.T) {
  1963  		testenv.MustHaveCGO(t)
  1964  		testBuildmodePIE(t, true, true)
  1965  	})
  1966  }
  1967  
  1968  func TestWindowsDefaultBuildmodIsPIE(t *testing.T) {
  1969  	if runtime.GOOS != "windows" {
  1970  		t.Skip("skipping windows only test")
  1971  	}
  1972  	tooSlow(t, "links binaries")
  1973  
  1974  	t.Run("non-cgo", func(t *testing.T) {
  1975  		testBuildmodePIE(t, false, false)
  1976  	})
  1977  	t.Run("cgo", func(t *testing.T) {
  1978  		testenv.MustHaveCGO(t)
  1979  		testBuildmodePIE(t, true, false)
  1980  	})
  1981  }
  1982  
  1983  func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) {
  1984  	tg := testgo(t)
  1985  	defer tg.cleanup()
  1986  	tg.parallel()
  1987  
  1988  	var s string
  1989  	if useCgo {
  1990  		s = `import "C";`
  1991  	}
  1992  	tg.tempFile("main.go", fmt.Sprintf(`package main;%s func main() { print("hello") }`, s))
  1993  	src := tg.path("main.go")
  1994  	obj := tg.path("main.exe")
  1995  	args := []string{"build"}
  1996  	if setBuildmodeToPIE {
  1997  		args = append(args, "-buildmode=pie")
  1998  	}
  1999  	args = append(args, "-o", obj, src)
  2000  	tg.run(args...)
  2001  
  2002  	switch runtime.GOOS {
  2003  	case "linux", "android", "freebsd":
  2004  		f, err := elf.Open(obj)
  2005  		if err != nil {
  2006  			t.Fatal(err)
  2007  		}
  2008  		defer f.Close()
  2009  		if f.Type != elf.ET_DYN {
  2010  			t.Errorf("PIE type must be ET_DYN, but %s", f.Type)
  2011  		}
  2012  	case "darwin", "ios":
  2013  		f, err := macho.Open(obj)
  2014  		if err != nil {
  2015  			t.Fatal(err)
  2016  		}
  2017  		defer f.Close()
  2018  		if f.Flags&macho.FlagDyldLink == 0 {
  2019  			t.Error("PIE must have DyldLink flag, but not")
  2020  		}
  2021  		if f.Flags&macho.FlagPIE == 0 {
  2022  			t.Error("PIE must have PIE flag, but not")
  2023  		}
  2024  	case "windows":
  2025  		f, err := pe.Open(obj)
  2026  		if err != nil {
  2027  			t.Fatal(err)
  2028  		}
  2029  		defer f.Close()
  2030  		if f.Section(".reloc") == nil {
  2031  			t.Error(".reloc section is not present")
  2032  		}
  2033  		if (f.FileHeader.Characteristics & pe.IMAGE_FILE_RELOCS_STRIPPED) != 0 {
  2034  			t.Error("IMAGE_FILE_RELOCS_STRIPPED flag is set")
  2035  		}
  2036  		var dc uint16
  2037  		switch oh := f.OptionalHeader.(type) {
  2038  		case *pe.OptionalHeader32:
  2039  			dc = oh.DllCharacteristics
  2040  		case *pe.OptionalHeader64:
  2041  			dc = oh.DllCharacteristics
  2042  			if (dc & pe.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) == 0 {
  2043  				t.Error("IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA flag is not set")
  2044  			}
  2045  		default:
  2046  			t.Fatalf("unexpected optional header type of %T", f.OptionalHeader)
  2047  		}
  2048  		if (dc & pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 {
  2049  			t.Error("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag is not set")
  2050  		}
  2051  	default:
  2052  		// testBuildmodePIE opens object files, so it needs to understand the object
  2053  		// file format.
  2054  		t.Skipf("skipping test: test helper does not support %s", runtime.GOOS)
  2055  	}
  2056  
  2057  	out, err := testenv.Command(t, obj).CombinedOutput()
  2058  	if err != nil {
  2059  		t.Fatal(err)
  2060  	}
  2061  
  2062  	if string(out) != "hello" {
  2063  		t.Errorf("got %q; want %q", out, "hello")
  2064  	}
  2065  }
  2066  
  2067  func TestUpxCompression(t *testing.T) {
  2068  	if runtime.GOOS != "linux" ||
  2069  		(runtime.GOARCH != "amd64" && runtime.GOARCH != "386") {
  2070  		t.Skipf("skipping upx test on %s/%s", runtime.GOOS, runtime.GOARCH)
  2071  	}
  2072  
  2073  	testenv.MustHaveExecPath(t, "upx")
  2074  	out, err := testenv.Command(t, "upx", "--version").CombinedOutput()
  2075  	if err != nil {
  2076  		t.Fatalf("upx --version failed: %v", err)
  2077  	}
  2078  
  2079  	// upx --version prints `upx <version>` in the first line of output:
  2080  	//   upx 3.94
  2081  	//   [...]
  2082  	re := regexp.MustCompile(`([[:digit:]]+)\.([[:digit:]]+)`)
  2083  	upxVersion := re.FindStringSubmatch(string(out))
  2084  	if len(upxVersion) != 3 {
  2085  		t.Fatalf("bad upx version string: %s", upxVersion)
  2086  	}
  2087  
  2088  	major, err1 := strconv.Atoi(upxVersion[1])
  2089  	minor, err2 := strconv.Atoi(upxVersion[2])
  2090  	if err1 != nil || err2 != nil {
  2091  		t.Fatalf("bad upx version string: %s", upxVersion[0])
  2092  	}
  2093  
  2094  	// Anything below 3.94 is known not to work with go binaries
  2095  	if (major < 3) || (major == 3 && minor < 94) {
  2096  		t.Skipf("skipping because upx version %v.%v is too old", major, minor)
  2097  	}
  2098  
  2099  	tg := testgo(t)
  2100  	defer tg.cleanup()
  2101  	tg.parallel()
  2102  
  2103  	tg.tempFile("main.go", `package main; import "fmt"; func main() { fmt.Print("hello upx") }`)
  2104  	src := tg.path("main.go")
  2105  	obj := tg.path("main")
  2106  	tg.run("build", "-o", obj, src)
  2107  
  2108  	out, err = testenv.Command(t, "upx", obj).CombinedOutput()
  2109  	if err != nil {
  2110  		t.Logf("executing upx\n%s\n", out)
  2111  		t.Fatalf("upx failed with %v", err)
  2112  	}
  2113  
  2114  	out, err = testenv.Command(t, obj).CombinedOutput()
  2115  	if err != nil {
  2116  		t.Logf("%s", out)
  2117  		t.Fatalf("running compressed go binary failed with error %s", err)
  2118  	}
  2119  	if string(out) != "hello upx" {
  2120  		t.Fatalf("bad output from compressed go binary:\ngot %q; want %q", out, "hello upx")
  2121  	}
  2122  }
  2123  
  2124  var gocacheverify = godebug.New("#gocacheverify")
  2125  
  2126  func TestCacheListStale(t *testing.T) {
  2127  	tooSlow(t, "links a binary")
  2128  	if gocacheverify.Value() == "1" {
  2129  		t.Skip("GODEBUG gocacheverify")
  2130  	}
  2131  
  2132  	tg := testgo(t)
  2133  	defer tg.cleanup()
  2134  	tg.parallel()
  2135  	tg.makeTempdir()
  2136  	tg.setenv("GOCACHE", tg.path("cache"))
  2137  	tg.tempFile("gopath/src/p/p.go", "package p; import _ \"q\"; func F(){}\n")
  2138  	tg.tempFile("gopath/src/q/q.go", "package q; func F(){}\n")
  2139  	tg.tempFile("gopath/src/m/m.go", "package main; import _ \"q\"; func main(){}\n")
  2140  
  2141  	tg.setenv("GOPATH", tg.path("gopath"))
  2142  	tg.run("install", "p", "m")
  2143  	tg.run("list", "-f={{.ImportPath}} {{.Stale}}", "m", "q", "p")
  2144  	tg.grepStdout("^m false", "m should not be stale")
  2145  	tg.grepStdout("^q true", "q should be stale")
  2146  	tg.grepStdout("^p false", "p should not be stale")
  2147  }
  2148  
  2149  func TestCacheCoverage(t *testing.T) {
  2150  	tooSlow(t, "links and runs a test binary with coverage enabled")
  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.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
  2159  	tg.makeTempdir()
  2160  
  2161  	tg.setenv("GOCACHE", tg.path("c1"))
  2162  	tg.run("test", "-cover", "-short", "strings")
  2163  	tg.run("test", "-cover", "-short", "math", "strings")
  2164  }
  2165  
  2166  func TestIssue22531(t *testing.T) {
  2167  	tooSlow(t, "links binaries")
  2168  	if gocacheverify.Value() == "1" {
  2169  		t.Skip("GODEBUG gocacheverify")
  2170  	}
  2171  
  2172  	tg := testgo(t)
  2173  	defer tg.cleanup()
  2174  	tg.parallel()
  2175  	tg.makeTempdir()
  2176  	tg.setenv("GOPATH", tg.tempdir)
  2177  	tg.setenv("GOCACHE", tg.path("cache"))
  2178  	tg.tempFile("src/m/main.go", "package main /* c1 */; func main() {}\n")
  2179  	tg.run("install", "-x", "m")
  2180  	tg.run("list", "-f", "{{.Stale}}", "m")
  2181  	tg.grepStdout("false", "reported m as stale after install")
  2182  	tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix))
  2183  
  2184  	// The link action ID did not include the full main build ID,
  2185  	// even though the full main build ID is written into the
  2186  	// eventual binary. That caused the following install to
  2187  	// be a no-op, thinking the gofmt binary was up-to-date,
  2188  	// even though .Stale could see it was not.
  2189  	tg.tempFile("src/m/main.go", "package main /* c2 */; func main() {}\n")
  2190  	tg.run("install", "-x", "m")
  2191  	tg.run("list", "-f", "{{.Stale}}", "m")
  2192  	tg.grepStdout("false", "reported m as stale after reinstall")
  2193  	tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix))
  2194  }
  2195  
  2196  func TestIssue22596(t *testing.T) {
  2197  	tooSlow(t, "links binaries")
  2198  	if gocacheverify.Value() == "1" {
  2199  		t.Skip("GODEBUG gocacheverify")
  2200  	}
  2201  
  2202  	tg := testgo(t)
  2203  	defer tg.cleanup()
  2204  	tg.parallel()
  2205  	tg.makeTempdir()
  2206  	tg.setenv("GOCACHE", tg.path("cache"))
  2207  	tg.tempFile("gopath1/src/p/p.go", "package p; func F(){}\n")
  2208  	tg.tempFile("gopath2/src/p/p.go", "package p; func F(){}\n")
  2209  
  2210  	tg.setenv("GOPATH", tg.path("gopath1"))
  2211  	tg.run("list", "-f={{.Target}}", "p")
  2212  	target1 := strings.TrimSpace(tg.getStdout())
  2213  	tg.run("install", "p")
  2214  	tg.wantNotStale("p", "", "p stale after install")
  2215  
  2216  	tg.setenv("GOPATH", tg.path("gopath2"))
  2217  	tg.run("list", "-f={{.Target}}", "p")
  2218  	target2 := strings.TrimSpace(tg.getStdout())
  2219  	tg.must(os.MkdirAll(filepath.Dir(target2), 0777))
  2220  	tg.must(copyFile(target1, target2, 0666))
  2221  	tg.wantStale("p", "build ID mismatch", "p not stale after copy from gopath1")
  2222  	tg.run("install", "p")
  2223  	tg.wantNotStale("p", "", "p stale after install2")
  2224  }
  2225  
  2226  func TestTestCache(t *testing.T) {
  2227  	tooSlow(t, "links and runs test binaries")
  2228  	if gocacheverify.Value() == "1" {
  2229  		t.Skip("GODEBUG gocacheverify")
  2230  	}
  2231  
  2232  	tg := testgo(t)
  2233  	defer tg.cleanup()
  2234  	tg.parallel()
  2235  	tg.makeTempdir()
  2236  	tg.setenv("GOPATH", tg.tempdir)
  2237  	tg.setenv("GOCACHE", tg.path("cache"))
  2238  
  2239  	// The -p=1 in the commands below just makes the -x output easier to read.
  2240  
  2241  	t.Log("\n\nINITIAL\n\n")
  2242  
  2243  	tg.tempFile("src/p1/p1.go", "package p1\nvar X =  1\n")
  2244  	tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\nvar X = 1\n")
  2245  	tg.tempFile("src/t/t1/t1_test.go", "package t\nimport \"testing\"\nfunc Test1(*testing.T) {}\n")
  2246  	tg.tempFile("src/t/t2/t2_test.go", "package t\nimport _ \"p1\"\nimport \"testing\"\nfunc Test2(*testing.T) {}\n")
  2247  	tg.tempFile("src/t/t3/t3_test.go", "package t\nimport \"p1\"\nimport \"testing\"\nfunc Test3(t *testing.T) {t.Log(p1.X)}\n")
  2248  	tg.tempFile("src/t/t4/t4_test.go", "package t\nimport \"p2\"\nimport \"testing\"\nfunc Test4(t *testing.T) {t.Log(p2.X)}")
  2249  	tg.run("test", "-x", "-v", "-short", "t/...")
  2250  
  2251  	t.Log("\n\nREPEAT\n\n")
  2252  
  2253  	tg.run("test", "-x", "-v", "-short", "t/...")
  2254  	tg.grepStdout(`ok  \tt/t1\t\(cached\)`, "did not cache t1")
  2255  	tg.grepStdout(`ok  \tt/t2\t\(cached\)`, "did not cache t2")
  2256  	tg.grepStdout(`ok  \tt/t3\t\(cached\)`, "did not cache t3")
  2257  	tg.grepStdout(`ok  \tt/t4\t\(cached\)`, "did not cache t4")
  2258  	tg.grepStderrNot(`[\\/](compile|gccgo) `, "incorrectly ran compiler")
  2259  	tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker")
  2260  	tg.grepStderrNot(`p[0-9]\.test`, "incorrectly ran test")
  2261  
  2262  	t.Log("\n\nCOMMENT\n\n")
  2263  
  2264  	// Changing the program text without affecting the compiled package
  2265  	// should result in the package being rebuilt but nothing more.
  2266  	tg.tempFile("src/p1/p1.go", "package p1\nvar X = 01\n")
  2267  	tg.run("test", "-p=1", "-x", "-v", "-short", "t/...")
  2268  	tg.grepStdout(`ok  \tt/t1\t\(cached\)`, "did not cache t1")
  2269  	tg.grepStdout(`ok  \tt/t2\t\(cached\)`, "did not cache t2")
  2270  	tg.grepStdout(`ok  \tt/t3\t\(cached\)`, "did not cache t3")
  2271  	tg.grepStdout(`ok  \tt/t4\t\(cached\)`, "did not cache t4")
  2272  	tg.grepStderrNot(`([\\/](compile|gccgo) ).*t[0-9]_test\.go`, "incorrectly ran compiler")
  2273  	tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker")
  2274  	tg.grepStderrNot(`t[0-9]\.test.*test\.short`, "incorrectly ran test")
  2275  
  2276  	t.Log("\n\nCHANGE\n\n")
  2277  
  2278  	// Changing the actual package should have limited effects.
  2279  	tg.tempFile("src/p1/p1.go", "package p1\nvar X = 02\n")
  2280  	tg.run("test", "-p=1", "-x", "-v", "-short", "t/...")
  2281  
  2282  	// p2 should have been rebuilt.
  2283  	tg.grepStderr(`([\\/]compile|gccgo).*p2.go`, "did not recompile p2")
  2284  
  2285  	// t1 does not import anything, should not have been rebuilt.
  2286  	tg.grepStderrNot(`([\\/]compile|gccgo).*t1_test.go`, "incorrectly recompiled t1")
  2287  	tg.grepStderrNot(`([\\/]link|gccgo).*t1_test`, "incorrectly relinked t1_test")
  2288  	tg.grepStdout(`ok  \tt/t1\t\(cached\)`, "did not cache t/t1")
  2289  
  2290  	// t2 imports p1 and must be rebuilt and relinked,
  2291  	// but the change should not have any effect on the test binary,
  2292  	// so the test should not have been rerun.
  2293  	tg.grepStderr(`([\\/]compile|gccgo).*t2_test.go`, "did not recompile t2")
  2294  	tg.grepStderr(`([\\/]link|gccgo).*t2\.test`, "did not relink t2_test")
  2295  	// This check does not currently work with gccgo, as garbage
  2296  	// collection of unused variables is not turned on by default.
  2297  	if runtime.Compiler != "gccgo" {
  2298  		tg.grepStdout(`ok  \tt/t2\t\(cached\)`, "did not cache t/t2")
  2299  	}
  2300  
  2301  	// t3 imports p1, and changing X changes t3's test binary.
  2302  	tg.grepStderr(`([\\/]compile|gccgo).*t3_test.go`, "did not recompile t3")
  2303  	tg.grepStderr(`([\\/]link|gccgo).*t3\.test`, "did not relink t3_test")
  2304  	tg.grepStderr(`t3\.test.*-test.short`, "did not rerun t3_test")
  2305  	tg.grepStdoutNot(`ok  \tt/t3\t\(cached\)`, "reported cached t3_test result")
  2306  
  2307  	// t4 imports p2, but p2 did not change, so t4 should be relinked, not recompiled,
  2308  	// and not rerun.
  2309  	tg.grepStderrNot(`([\\/]compile|gccgo).*t4_test.go`, "incorrectly recompiled t4")
  2310  	tg.grepStderr(`([\\/]link|gccgo).*t4\.test`, "did not relink t4_test")
  2311  	// This check does not currently work with gccgo, as garbage
  2312  	// collection of unused variables is not turned on by default.
  2313  	if runtime.Compiler != "gccgo" {
  2314  		tg.grepStdout(`ok  \tt/t4\t\(cached\)`, "did not cache t/t4")
  2315  	}
  2316  }
  2317  
  2318  func TestTestSkipVetAfterFailedBuild(t *testing.T) {
  2319  	tg := testgo(t)
  2320  	defer tg.cleanup()
  2321  	tg.parallel()
  2322  
  2323  	tg.tempFile("x_test.go", `package x
  2324  		func f() {
  2325  			return 1
  2326  		}
  2327  	`)
  2328  
  2329  	tg.runFail("test", tg.path("x_test.go"))
  2330  	tg.grepStderrNot(`vet`, "vet should be skipped after the failed build")
  2331  }
  2332  
  2333  func TestTestVetRebuild(t *testing.T) {
  2334  	tooSlow(t, "links and runs test binaries")
  2335  
  2336  	tg := testgo(t)
  2337  	defer tg.cleanup()
  2338  	tg.parallel()
  2339  
  2340  	// golang.org/issue/23701.
  2341  	// b_test imports b with augmented method from export_test.go.
  2342  	// b_test also imports a, which imports b.
  2343  	// Must not accidentally see un-augmented b propagate through a to b_test.
  2344  	tg.tempFile("src/a/a.go", `package a
  2345  		import "b"
  2346  		type Type struct{}
  2347  		func (*Type) M() b.T {return 0}
  2348  	`)
  2349  	tg.tempFile("src/b/b.go", `package b
  2350  		type T int
  2351  		type I interface {M() T}
  2352  	`)
  2353  	tg.tempFile("src/b/export_test.go", `package b
  2354  		func (*T) Method() *T { return nil }
  2355  	`)
  2356  	tg.tempFile("src/b/b_test.go", `package b_test
  2357  		import (
  2358  			"testing"
  2359  			"a"
  2360  			. "b"
  2361  		)
  2362  		func TestBroken(t *testing.T) {
  2363  			x := new(T)
  2364  			x.Method()
  2365  			_ = new(a.Type)
  2366  		}
  2367  	`)
  2368  
  2369  	tg.setenv("GOPATH", tg.path("."))
  2370  	tg.run("test", "b")
  2371  	tg.run("vet", "b")
  2372  }
  2373  
  2374  func TestInstallDeps(t *testing.T) {
  2375  	tooSlow(t, "links a binary")
  2376  
  2377  	tg := testgo(t)
  2378  	defer tg.cleanup()
  2379  	tg.parallel()
  2380  	tg.makeTempdir()
  2381  	tg.setenv("GOPATH", tg.tempdir)
  2382  
  2383  	tg.tempFile("src/p1/p1.go", "package p1\nvar X =  1\n")
  2384  	tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\n")
  2385  	tg.tempFile("src/main1/main.go", "package main\nimport _ \"p2\"\nfunc main() {}\n")
  2386  
  2387  	tg.run("list", "-f={{.Target}}", "p1")
  2388  	p1 := strings.TrimSpace(tg.getStdout())
  2389  	tg.run("list", "-f={{.Target}}", "p2")
  2390  	p2 := strings.TrimSpace(tg.getStdout())
  2391  	tg.run("list", "-f={{.Target}}", "main1")
  2392  	main1 := strings.TrimSpace(tg.getStdout())
  2393  
  2394  	tg.run("install", "main1")
  2395  
  2396  	tg.mustExist(main1)
  2397  	tg.mustNotExist(p2)
  2398  	tg.mustNotExist(p1)
  2399  
  2400  	tg.run("install", "p2")
  2401  	tg.mustExist(p2)
  2402  	tg.mustNotExist(p1)
  2403  }
  2404  
  2405  // Issue 22986.
  2406  func TestImportPath(t *testing.T) {
  2407  	tooSlow(t, "links and runs a test binary")
  2408  
  2409  	tg := testgo(t)
  2410  	defer tg.cleanup()
  2411  	tg.parallel()
  2412  
  2413  	tg.tempFile("src/a/a.go", `
  2414  package main
  2415  
  2416  import (
  2417  	"log"
  2418  	p "a/p-1.0"
  2419  )
  2420  
  2421  func main() {
  2422  	if !p.V {
  2423  		log.Fatal("false")
  2424  	}
  2425  }`)
  2426  
  2427  	tg.tempFile("src/a/a_test.go", `
  2428  package main_test
  2429  
  2430  import (
  2431  	p "a/p-1.0"
  2432  	"testing"
  2433  )
  2434  
  2435  func TestV(t *testing.T) {
  2436  	if !p.V {
  2437  		t.Fatal("false")
  2438  	}
  2439  }`)
  2440  
  2441  	tg.tempFile("src/a/p-1.0/p.go", `
  2442  package p
  2443  
  2444  var V = true
  2445  
  2446  func init() {}
  2447  `)
  2448  
  2449  	tg.setenv("GOPATH", tg.path("."))
  2450  	tg.run("build", "-o", tg.path("a.exe"), "a")
  2451  	tg.run("test", "a")
  2452  }
  2453  
  2454  func TestBadCommandLines(t *testing.T) {
  2455  	tg := testgo(t)
  2456  	defer tg.cleanup()
  2457  	tg.parallel()
  2458  
  2459  	tg.tempFile("src/x/x.go", "package x\n")
  2460  	tg.setenv("GOPATH", tg.path("."))
  2461  
  2462  	tg.run("build", "x")
  2463  
  2464  	tg.tempFile("src/x/@y.go", "package x\n")
  2465  	tg.runFail("build", "x")
  2466  	tg.grepStderr("invalid input file name \"@y.go\"", "did not reject @y.go")
  2467  	tg.must(os.Remove(tg.path("src/x/@y.go")))
  2468  
  2469  	tg.tempFile("src/x/-y.go", "package x\n")
  2470  	tg.runFail("build", "x")
  2471  	tg.grepStderr("invalid input file name \"-y.go\"", "did not reject -y.go")
  2472  	tg.must(os.Remove(tg.path("src/x/-y.go")))
  2473  
  2474  	if runtime.Compiler == "gccgo" {
  2475  		tg.runFail("build", "-gccgoflags=all=@x", "x")
  2476  	} else {
  2477  		tg.runFail("build", "-gcflags=all=@x", "x")
  2478  	}
  2479  	tg.grepStderr("invalid command-line argument @x in command", "did not reject @x during exec")
  2480  
  2481  	tg.tempFile("src/@x/x.go", "package x\n")
  2482  	tg.setenv("GOPATH", tg.path("."))
  2483  	tg.runFail("build", "@x")
  2484  	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")
  2485  
  2486  	tg.tempFile("src/@x/y/y.go", "package y\n")
  2487  	tg.setenv("GOPATH", tg.path("."))
  2488  	tg.runFail("build", "@x/y")
  2489  	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")
  2490  
  2491  	tg.tempFile("src/-x/x.go", "package x\n")
  2492  	tg.setenv("GOPATH", tg.path("."))
  2493  	tg.runFail("build", "--", "-x")
  2494  	tg.grepStderr("invalid import path \"-x\"", "did not reject -x import path")
  2495  
  2496  	tg.tempFile("src/-x/y/y.go", "package y\n")
  2497  	tg.setenv("GOPATH", tg.path("."))
  2498  	tg.runFail("build", "--", "-x/y")
  2499  	tg.grepStderr("invalid import path \"-x/y\"", "did not reject -x/y import path")
  2500  }
  2501  
  2502  func TestTwoPkgConfigs(t *testing.T) {
  2503  	testenv.MustHaveCGO(t)
  2504  	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
  2505  		t.Skipf("no shell scripts on %s", runtime.GOOS)
  2506  	}
  2507  	tooSlow(t, "builds a package with cgo dependencies")
  2508  
  2509  	tg := testgo(t)
  2510  	defer tg.cleanup()
  2511  	tg.parallel()
  2512  	tg.tempFile("src/x/a.go", `package x
  2513  		// #cgo pkg-config: --static a
  2514  		import "C"
  2515  	`)
  2516  	tg.tempFile("src/x/b.go", `package x
  2517  		// #cgo pkg-config: --static a
  2518  		import "C"
  2519  	`)
  2520  	tg.tempFile("pkg-config.sh", `#!/bin/sh
  2521  echo $* >>`+tg.path("pkg-config.out"))
  2522  	tg.must(os.Chmod(tg.path("pkg-config.sh"), 0755))
  2523  	tg.setenv("GOPATH", tg.path("."))
  2524  	tg.setenv("PKG_CONFIG", tg.path("pkg-config.sh"))
  2525  	tg.run("build", "x")
  2526  	out, err := os.ReadFile(tg.path("pkg-config.out"))
  2527  	tg.must(err)
  2528  	out = bytes.TrimSpace(out)
  2529  	want := "--cflags --static --static -- a a\n--libs --static --static -- a a"
  2530  	if !bytes.Equal(out, []byte(want)) {
  2531  		t.Errorf("got %q want %q", out, want)
  2532  	}
  2533  }
  2534  
  2535  func TestCgoCache(t *testing.T) {
  2536  	testenv.MustHaveCGO(t)
  2537  	tooSlow(t, "builds a package with cgo dependencies")
  2538  
  2539  	tg := testgo(t)
  2540  	defer tg.cleanup()
  2541  	tg.parallel()
  2542  	tg.tempFile("src/x/a.go", `package main
  2543  		// #ifndef VAL
  2544  		// #define VAL 0
  2545  		// #endif
  2546  		// int val = VAL;
  2547  		import "C"
  2548  		import "fmt"
  2549  		func main() { fmt.Println(C.val) }
  2550  	`)
  2551  	tg.setenv("GOPATH", tg.path("."))
  2552  	exe := tg.path("x.exe")
  2553  	tg.run("build", "-o", exe, "x")
  2554  	tg.setenv("CGO_LDFLAGS", "-lnosuchlibraryexists")
  2555  	tg.runFail("build", "-o", exe, "x")
  2556  	tg.grepStderr(`nosuchlibraryexists`, "did not run linker with changed CGO_LDFLAGS")
  2557  }
  2558  
  2559  // Issue 23982
  2560  func TestFilepathUnderCwdFormat(t *testing.T) {
  2561  	tg := testgo(t)
  2562  	defer tg.cleanup()
  2563  	tg.parallel()
  2564  	tg.run("test", "-x", "-cover", "log")
  2565  	tg.grepStderrNot(`\.log\.cover\.go`, "-x output should contain correctly formatted filepath under cwd")
  2566  }
  2567  
  2568  // Issue 24396.
  2569  func TestDontReportRemoveOfEmptyDir(t *testing.T) {
  2570  	tg := testgo(t)
  2571  	defer tg.cleanup()
  2572  	tg.parallel()
  2573  	tg.tempFile("src/a/a.go", `package a`)
  2574  	tg.setenv("GOPATH", tg.path("."))
  2575  	tg.run("install", "-x", "a")
  2576  	tg.run("install", "-x", "a")
  2577  	// The second install should have printed only a WORK= line,
  2578  	// nothing else.
  2579  	if bytes.Count(tg.stdout.Bytes(), []byte{'\n'})+bytes.Count(tg.stderr.Bytes(), []byte{'\n'}) > 1 {
  2580  		t.Error("unnecessary output when installing installed package")
  2581  	}
  2582  }
  2583  
  2584  // Issue 24704.
  2585  func TestLinkerTmpDirIsDeleted(t *testing.T) {
  2586  	skipIfGccgo(t, "gccgo does not use cmd/link")
  2587  	testenv.MustHaveCGO(t)
  2588  	tooSlow(t, "builds a package with cgo dependencies")
  2589  
  2590  	tg := testgo(t)
  2591  	defer tg.cleanup()
  2592  	tg.parallel()
  2593  	tg.tempFile("a.go", `package main; import "C"; func main() {}`)
  2594  	tg.run("build", "-ldflags", "-v", "-o", os.DevNull, tg.path("a.go"))
  2595  	// Find line that has "host link:" in linker output.
  2596  	stderr := tg.getStderr()
  2597  	var hostLinkLine string
  2598  	for _, line := range strings.Split(stderr, "\n") {
  2599  		if !strings.Contains(line, "host link:") {
  2600  			continue
  2601  		}
  2602  		hostLinkLine = line
  2603  		break
  2604  	}
  2605  	if hostLinkLine == "" {
  2606  		t.Fatal(`fail to find with "host link:" string in linker output`)
  2607  	}
  2608  	// Find parameter, like "/tmp/go-link-408556474/go.o" inside of
  2609  	// "host link:" line, and extract temp directory /tmp/go-link-408556474
  2610  	// out of it.
  2611  	tmpdir := hostLinkLine
  2612  	i := strings.Index(tmpdir, `go.o"`)
  2613  	if i == -1 {
  2614  		t.Fatalf(`fail to find "go.o" in "host link:" line %q`, hostLinkLine)
  2615  	}
  2616  	tmpdir = tmpdir[:i-1]
  2617  	i = strings.LastIndex(tmpdir, `"`)
  2618  	if i == -1 {
  2619  		t.Fatalf(`fail to find " in "host link:" line %q`, hostLinkLine)
  2620  	}
  2621  	tmpdir = tmpdir[i+1:]
  2622  	// Verify that temp directory has been removed.
  2623  	_, err := os.Stat(tmpdir)
  2624  	if err == nil {
  2625  		t.Fatalf("temp directory %q has not been removed", tmpdir)
  2626  	}
  2627  	if !os.IsNotExist(err) {
  2628  		t.Fatalf("Stat(%q) returns unexpected error: %v", tmpdir, err)
  2629  	}
  2630  }
  2631  
  2632  // Issue 25093.
  2633  func TestCoverpkgTestOnly(t *testing.T) {
  2634  	skipIfGccgo(t, "gccgo has no cover tool")
  2635  	tooSlow(t, "links and runs a test binary with coverage enabled")
  2636  
  2637  	tg := testgo(t)
  2638  	defer tg.cleanup()
  2639  	tg.parallel()
  2640  	tg.tempFile("src/a/a.go", `package a
  2641  		func F(i int) int {
  2642  			return i*i
  2643  		}`)
  2644  	tg.tempFile("src/atest/a_test.go", `
  2645  		package a_test
  2646  		import ( "a"; "testing" )
  2647  		func TestF(t *testing.T) { a.F(2) }
  2648  	`)
  2649  	tg.setenv("GOPATH", tg.path("."))
  2650  	tg.run("test", "-coverpkg=a", "atest")
  2651  	tg.grepStderrNot("no packages being tested depend on matches", "bad match message")
  2652  	tg.grepStdout("coverage: 100", "no coverage")
  2653  }
  2654  
  2655  // Regression test for golang.org/issue/34499: version command should not crash
  2656  // when executed in a deleted directory on Linux.
  2657  func TestExecInDeletedDir(t *testing.T) {
  2658  	switch runtime.GOOS {
  2659  	case "windows", "plan9",
  2660  		"aix",                // Fails with "device busy".
  2661  		"solaris", "illumos": // Fails with "invalid argument".
  2662  		t.Skipf("%v does not support removing the current working directory", runtime.GOOS)
  2663  	}
  2664  	tg := testgo(t)
  2665  	defer tg.cleanup()
  2666  
  2667  	tg.makeTempdir()
  2668  	t.Chdir(tg.tempdir)
  2669  
  2670  	tg.check(os.Remove(tg.tempdir))
  2671  
  2672  	// `go version` should not fail
  2673  	tg.run("version")
  2674  }
  2675  

View as plain text