Source file src/cmd/go/go_test.go

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main_test
     6  
     7  import (
     8  	"bytes"
     9  	"debug/elf"
    10  	"debug/macho"
    11  	"debug/pe"
    12  	"encoding/binary"
    13  	"flag"
    14  	"fmt"
    15  	"go/format"
    16  	"internal/godebug"
    17  	"internal/platform"
    18  	"internal/testenv"
    19  	"io"
    20  	"io/fs"
    21  	"log"
    22  	"math"
    23  	"os"
    24  	"os/exec"
    25  	"path/filepath"
    26  	"regexp"
    27  	"runtime"
    28  	"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/robustio"
    38  	"cmd/go/internal/search"
    39  	"cmd/go/internal/toolchain"
    40  	"cmd/go/internal/vcs"
    41  	"cmd/go/internal/vcweb/vcstest"
    42  	"cmd/go/internal/web"
    43  	"cmd/go/internal/work"
    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 []web.Interceptor
   148  			for _, host := range vcstest.Hosts {
   149  				interceptors = append(interceptors,
   150  					web.Interceptor{Scheme: "http", FromHost: host, ToHost: vcsTestHost},
   151  					web.Interceptor{Scheme: "https", FromHost: host, ToHost: vcsTestTLSHost, Client: vcsTestClient})
   152  			}
   153  			web.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, "TESTGOVCS=panic")
   472  		}
   473  	}
   474  	for i, v := range tg.env {
   475  		if strings.HasPrefix(v, name+"=") {
   476  			tg.env = append(tg.env[:i], tg.env[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 runtime/internal/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/runtime/internal/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 runtime/internal/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: runtime/internal", "./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: runtime", "./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", "stale dependency: runtime/internal", "./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  func TestPackageMainTestCompilerFlags(t *testing.T) {
   976  	tg := testgo(t)
   977  	defer tg.cleanup()
   978  	tg.parallel()
   979  	tg.makeTempdir()
   980  	tg.setenv("GOPATH", tg.path("."))
   981  	tg.tempFile("src/p1/p1.go", "package main\n")
   982  	tg.tempFile("src/p1/p1_test.go", "package main\nimport \"testing\"\nfunc Test(t *testing.T){}\n")
   983  	tg.run("test", "-c", "-n", "p1")
   984  	tg.grepBothNot(`([\\/]compile|gccgo).* (-p main|-fgo-pkgpath=main).*p1\.go`, "should not have run compile -p main p1.go")
   985  	tg.grepStderr(`([\\/]compile|gccgo).* (-p p1|-fgo-pkgpath=p1).*p1\.go`, "should have run compile -p p1 p1.go")
   986  }
   987  
   988  // Issue 4104.
   989  func TestGoTestWithPackageListedMultipleTimes(t *testing.T) {
   990  	tooSlow(t, "links and runs a test")
   991  
   992  	tg := testgo(t)
   993  	defer tg.cleanup()
   994  	tg.parallel()
   995  	tg.run("test", "errors", "errors", "errors", "errors", "errors")
   996  	if strings.Contains(strings.TrimSpace(tg.getStdout()), "\n") {
   997  		t.Error("go test errors errors errors errors errors tested the same package multiple times")
   998  	}
   999  }
  1000  
  1001  func TestGoListHasAConsistentOrder(t *testing.T) {
  1002  	tooSlow(t, "walks all of GOROOT/src twice")
  1003  
  1004  	tg := testgo(t)
  1005  	defer tg.cleanup()
  1006  	tg.parallel()
  1007  	tg.run("list", "std")
  1008  	first := tg.getStdout()
  1009  	tg.run("list", "std")
  1010  	if first != tg.getStdout() {
  1011  		t.Error("go list std ordering is inconsistent")
  1012  	}
  1013  }
  1014  
  1015  func TestGoListStdDoesNotIncludeCommands(t *testing.T) {
  1016  	tooSlow(t, "walks all of GOROOT/src")
  1017  
  1018  	tg := testgo(t)
  1019  	defer tg.cleanup()
  1020  	tg.parallel()
  1021  	tg.run("list", "std")
  1022  	tg.grepStdoutNot("cmd/", "go list std shows commands")
  1023  }
  1024  
  1025  func TestGoListCmdOnlyShowsCommands(t *testing.T) {
  1026  	skipIfGccgo(t, "gccgo does not have GOROOT")
  1027  	tooSlow(t, "walks all of GOROOT/src/cmd")
  1028  
  1029  	tg := testgo(t)
  1030  	defer tg.cleanup()
  1031  	tg.parallel()
  1032  	tg.run("list", "cmd")
  1033  	out := strings.TrimSpace(tg.getStdout())
  1034  	for _, line := range strings.Split(out, "\n") {
  1035  		if !strings.Contains(line, "cmd/") {
  1036  			t.Error("go list cmd shows non-commands")
  1037  			break
  1038  		}
  1039  	}
  1040  }
  1041  
  1042  func TestGoListDeps(t *testing.T) {
  1043  	tg := testgo(t)
  1044  	defer tg.cleanup()
  1045  	tg.parallel()
  1046  	tg.tempDir("src/p1/p2/p3/p4")
  1047  	tg.setenv("GOPATH", tg.path("."))
  1048  	tg.tempFile("src/p1/p.go", "package p1\nimport _ \"p1/p2\"\n")
  1049  	tg.tempFile("src/p1/p2/p.go", "package p2\nimport _ \"p1/p2/p3\"\n")
  1050  	tg.tempFile("src/p1/p2/p3/p.go", "package p3\nimport _ \"p1/p2/p3/p4\"\n")
  1051  	tg.tempFile("src/p1/p2/p3/p4/p.go", "package p4\n")
  1052  	tg.run("list", "-f", "{{.Deps}}", "p1")
  1053  	tg.grepStdout("p1/p2/p3/p4", "Deps(p1) does not mention p4")
  1054  
  1055  	tg.run("list", "-deps", "p1")
  1056  	tg.grepStdout("p1/p2/p3/p4", "-deps p1 does not mention p4")
  1057  
  1058  	if runtime.Compiler != "gccgo" {
  1059  		// Check the list is in dependency order.
  1060  		tg.run("list", "-deps", "math")
  1061  		want := "unsafe\ninternal/cpu\nmath/bits\nmath\n"
  1062  		out := tg.stdout.String()
  1063  		if !strings.Contains(out, "internal/cpu") {
  1064  			// Some systems don't use internal/cpu.
  1065  			want = "unsafe\nmath/bits\nmath\n"
  1066  		}
  1067  		if tg.stdout.String() != want {
  1068  			t.Fatalf("list -deps math: wrong order\nhave %q\nwant %q", tg.stdout.String(), want)
  1069  		}
  1070  	}
  1071  }
  1072  
  1073  func TestGoListTest(t *testing.T) {
  1074  	skipIfGccgo(t, "gccgo does not have standard packages")
  1075  	tg := testgo(t)
  1076  	defer tg.cleanup()
  1077  	tg.parallel()
  1078  	tg.makeTempdir()
  1079  	tg.setenv("GOCACHE", tg.tempdir)
  1080  
  1081  	tg.run("list", "-test", "-deps", "bytes")
  1082  	tg.grepStdout(`^bytes.test$`, "missing test main")
  1083  	tg.grepStdout(`^bytes$`, "missing real bytes")
  1084  	tg.grepStdout(`^bytes \[bytes.test\]$`, "missing test copy of bytes")
  1085  	tg.grepStdout(`^testing \[bytes.test\]$`, "missing test copy of testing")
  1086  	tg.grepStdoutNot(`^testing$`, "unexpected real copy of testing")
  1087  
  1088  	tg.run("list", "-test", "bytes")
  1089  	tg.grepStdout(`^bytes.test$`, "missing test main")
  1090  	tg.grepStdout(`^bytes$`, "missing real bytes")
  1091  	tg.grepStdout(`^bytes \[bytes.test\]$`, "unexpected test copy of bytes")
  1092  	tg.grepStdoutNot(`^testing \[bytes.test\]$`, "unexpected test copy of testing")
  1093  	tg.grepStdoutNot(`^testing$`, "unexpected real copy of testing")
  1094  
  1095  	tg.run("list", "-test", "cmd/buildid", "cmd/doc")
  1096  	tg.grepStdout(`^cmd/buildid$`, "missing cmd/buildid")
  1097  	tg.grepStdout(`^cmd/doc$`, "missing cmd/doc")
  1098  	tg.grepStdout(`^cmd/doc\.test$`, "missing cmd/doc test")
  1099  	tg.grepStdoutNot(`^cmd/buildid\.test$`, "unexpected cmd/buildid test")
  1100  	tg.grepStdoutNot(`^testing`, "unexpected testing")
  1101  
  1102  	tg.run("list", "-test", "runtime/cgo")
  1103  	tg.grepStdout(`^runtime/cgo$`, "missing runtime/cgo")
  1104  
  1105  	tg.run("list", "-deps", "-f", "{{if .DepOnly}}{{.ImportPath}}{{end}}", "sort")
  1106  	tg.grepStdout(`^internal/reflectlite$`, "missing internal/reflectlite")
  1107  	tg.grepStdoutNot(`^sort`, "unexpected sort")
  1108  }
  1109  
  1110  func TestGoListCompiledCgo(t *testing.T) {
  1111  	tooSlow(t, "compiles cgo files")
  1112  
  1113  	tg := testgo(t)
  1114  	defer tg.cleanup()
  1115  	tg.parallel()
  1116  	tg.makeTempdir()
  1117  	tg.setenv("GOCACHE", tg.tempdir)
  1118  
  1119  	tg.run("list", "-f", `{{join .CgoFiles "\n"}}`, "net")
  1120  	if tg.stdout.String() == "" {
  1121  		t.Skip("net does not use cgo")
  1122  	}
  1123  	if strings.Contains(tg.stdout.String(), tg.tempdir) {
  1124  		t.Fatalf(".CgoFiles unexpectedly mentioned cache %s", tg.tempdir)
  1125  	}
  1126  	tg.run("list", "-compiled", "-f", `{{.Dir}}{{"\n"}}{{join .CompiledGoFiles "\n"}}`, "net")
  1127  	if !strings.Contains(tg.stdout.String(), tg.tempdir) {
  1128  		t.Fatalf(".CompiledGoFiles with -compiled did not mention cache %s", tg.tempdir)
  1129  	}
  1130  	dir := ""
  1131  	for _, file := range strings.Split(tg.stdout.String(), "\n") {
  1132  		if file == "" {
  1133  			continue
  1134  		}
  1135  		if dir == "" {
  1136  			dir = file
  1137  			continue
  1138  		}
  1139  		if !strings.Contains(file, "/") && !strings.Contains(file, `\`) {
  1140  			file = filepath.Join(dir, file)
  1141  		}
  1142  		if _, err := os.Stat(file); err != nil {
  1143  			t.Fatalf("cannot find .CompiledGoFiles result %s: %v", file, err)
  1144  		}
  1145  	}
  1146  }
  1147  
  1148  func TestGoListExport(t *testing.T) {
  1149  	skipIfGccgo(t, "gccgo does not have standard packages")
  1150  	tg := testgo(t)
  1151  	defer tg.cleanup()
  1152  	tg.parallel()
  1153  	tg.makeTempdir()
  1154  	tg.setenv("GOCACHE", tg.tempdir)
  1155  
  1156  	tg.run("list", "-f", "{{.Export}}", "strings")
  1157  	if tg.stdout.String() != "" {
  1158  		t.Fatalf(".Export without -export unexpectedly set")
  1159  	}
  1160  	tg.run("list", "-export", "-f", "{{.Export}}", "strings")
  1161  	file := strings.TrimSpace(tg.stdout.String())
  1162  	if file == "" {
  1163  		t.Fatalf(".Export with -export was empty")
  1164  	}
  1165  	if _, err := os.Stat(file); err != nil {
  1166  		t.Fatalf("cannot find .Export result %s: %v", file, err)
  1167  	}
  1168  
  1169  	tg.run("list", "-export", "-f", "{{.BuildID}}", "strings")
  1170  	buildID := strings.TrimSpace(tg.stdout.String())
  1171  	if buildID == "" {
  1172  		t.Fatalf(".BuildID with -export was empty")
  1173  	}
  1174  
  1175  	tg.run("tool", "buildid", file)
  1176  	toolBuildID := strings.TrimSpace(tg.stdout.String())
  1177  	if buildID != toolBuildID {
  1178  		t.Fatalf(".BuildID with -export %q disagrees with 'go tool buildid' %q", buildID, toolBuildID)
  1179  	}
  1180  }
  1181  
  1182  // Issue 4096. Validate the output of unsuccessful go install foo/quxx.
  1183  func TestUnsuccessfulGoInstallShouldMentionMissingPackage(t *testing.T) {
  1184  	tg := testgo(t)
  1185  	defer tg.cleanup()
  1186  	tg.parallel()
  1187  	tg.runFail("install", "foo/quxx")
  1188  	if tg.grepCountBoth(`cannot find package "foo/quxx" in any of`) != 1 {
  1189  		t.Error(`go install foo/quxx expected error: .*cannot find package "foo/quxx" in any of`)
  1190  	}
  1191  }
  1192  
  1193  func TestGOROOTSearchFailureReporting(t *testing.T) {
  1194  	tg := testgo(t)
  1195  	defer tg.cleanup()
  1196  	tg.parallel()
  1197  	tg.runFail("install", "foo/quxx")
  1198  	if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("foo", "quxx"))+` \(from \$GOROOT\)$`) != 1 {
  1199  		t.Error(`go install foo/quxx expected error: .*foo/quxx (from $GOROOT)`)
  1200  	}
  1201  }
  1202  
  1203  func TestMultipleGOPATHEntriesReportedSeparately(t *testing.T) {
  1204  	tg := testgo(t)
  1205  	defer tg.cleanup()
  1206  	tg.parallel()
  1207  	sep := string(filepath.ListSeparator)
  1208  	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
  1209  	tg.runFail("install", "foo/quxx")
  1210  	if tg.grepCountBoth(`testdata[/\\].[/\\]src[/\\]foo[/\\]quxx`) != 2 {
  1211  		t.Error(`go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)\n.*testdata/b/src/foo/quxx`)
  1212  	}
  1213  }
  1214  
  1215  // Test (from $GOPATH) annotation is reported for the first GOPATH entry,
  1216  func TestMentionGOPATHInFirstGOPATHEntry(t *testing.T) {
  1217  	tg := testgo(t)
  1218  	defer tg.cleanup()
  1219  	tg.parallel()
  1220  	sep := string(filepath.ListSeparator)
  1221  	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
  1222  	tg.runFail("install", "foo/quxx")
  1223  	if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("testdata", "a", "src", "foo", "quxx"))+` \(from \$GOPATH\)$`) != 1 {
  1224  		t.Error(`go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)`)
  1225  	}
  1226  }
  1227  
  1228  // but not on the second.
  1229  func TestMentionGOPATHNotOnSecondEntry(t *testing.T) {
  1230  	tg := testgo(t)
  1231  	defer tg.cleanup()
  1232  	tg.parallel()
  1233  	sep := string(filepath.ListSeparator)
  1234  	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
  1235  	tg.runFail("install", "foo/quxx")
  1236  	if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("testdata", "b", "src", "foo", "quxx"))+`$`) != 1 {
  1237  		t.Error(`go install foo/quxx expected error: .*testdata/b/src/foo/quxx`)
  1238  	}
  1239  }
  1240  
  1241  func homeEnvName() string {
  1242  	switch runtime.GOOS {
  1243  	case "windows":
  1244  		return "USERPROFILE"
  1245  	case "plan9":
  1246  		return "home"
  1247  	default:
  1248  		return "HOME"
  1249  	}
  1250  }
  1251  
  1252  func tempEnvName() string {
  1253  	switch runtime.GOOS {
  1254  	case "windows":
  1255  		return "TMP"
  1256  	case "plan9":
  1257  		return "TMPDIR" // actually plan 9 doesn't have one at all but this is fine
  1258  	default:
  1259  		return "TMPDIR"
  1260  	}
  1261  }
  1262  
  1263  func pathEnvName() string {
  1264  	switch runtime.GOOS {
  1265  	case "plan9":
  1266  		return "path"
  1267  	default:
  1268  		return "PATH"
  1269  	}
  1270  }
  1271  
  1272  func TestDefaultGOPATH(t *testing.T) {
  1273  	tg := testgo(t)
  1274  	defer tg.cleanup()
  1275  	tg.parallel()
  1276  	tg.tempDir("home/go")
  1277  	tg.setenv(homeEnvName(), tg.path("home"))
  1278  	// Set TEST_TELEMETRY_DIR to a path that doesn't exist
  1279  	// so that the counter uploading code doesn't write
  1280  	// the counter token file to the temp dir after the test finishes.
  1281  	tg.setenv("TEST_TELEMETRY_DIR", "/no-telemetry-dir")
  1282  
  1283  	tg.run("env", "GOPATH")
  1284  	tg.grepStdout(regexp.QuoteMeta(tg.path("home/go")), "want GOPATH=$HOME/go")
  1285  
  1286  	tg.setenv("GOROOT", tg.path("home/go"))
  1287  	tg.run("env", "GOPATH")
  1288  	tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go")
  1289  
  1290  	tg.setenv("GOROOT", tg.path("home/go")+"/")
  1291  	tg.run("env", "GOPATH")
  1292  	tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go/")
  1293  }
  1294  
  1295  func TestDefaultGOPATHPrintedSearchList(t *testing.T) {
  1296  	tg := testgo(t)
  1297  	defer tg.cleanup()
  1298  	tg.parallel()
  1299  	tg.setenv("GOPATH", "")
  1300  	tg.tempDir("home")
  1301  	tg.setenv(homeEnvName(), tg.path("home"))
  1302  	// Set TEST_TELEMETRY_DIR to a path that doesn't exist
  1303  	// so that the counter uploading code doesn't write
  1304  	// the counter token file to the temp dir after the test finishes.
  1305  	tg.setenv("TEST_TELEMETRY_DIR", "/no-telemetry-dir")
  1306  
  1307  	tg.runFail("install", "github.com/golang/example/hello")
  1308  	tg.grepStderr(regexp.QuoteMeta(tg.path("home/go/src/github.com/golang/example/hello"))+`.*from \$GOPATH`, "expected default GOPATH")
  1309  }
  1310  
  1311  func TestLdflagsArgumentsWithSpacesIssue3941(t *testing.T) {
  1312  	skipIfGccgo(t, "gccgo does not support -ldflags -X")
  1313  	tooSlow(t, "compiles and links a binary")
  1314  
  1315  	tg := testgo(t)
  1316  	defer tg.cleanup()
  1317  	tg.parallel()
  1318  	tg.tempFile("main.go", `package main
  1319  		var extern string
  1320  		func main() {
  1321  			println(extern)
  1322  		}`)
  1323  	tg.run("run", "-ldflags", `-X "main.extern=hello world"`, tg.path("main.go"))
  1324  	tg.grepStderr("^hello world", `ldflags -X "main.extern=hello world"' failed`)
  1325  }
  1326  
  1327  func TestLdFlagsLongArgumentsIssue42295(t *testing.T) {
  1328  	// Test the extremely long command line arguments that contain '\n' characters
  1329  	// get encoded and passed correctly.
  1330  	skipIfGccgo(t, "gccgo does not support -ldflags -X")
  1331  	tooSlow(t, "compiles and links a binary")
  1332  
  1333  	tg := testgo(t)
  1334  	defer tg.cleanup()
  1335  	tg.parallel()
  1336  	tg.tempFile("main.go", `package main
  1337  		var extern string
  1338  		func main() {
  1339  			print(extern)
  1340  		}`)
  1341  	testStr := "test test test test test \n\\ "
  1342  	var buf strings.Builder
  1343  	for buf.Len() < sys.ExecArgLengthLimit+1 {
  1344  		buf.WriteString(testStr)
  1345  	}
  1346  	tg.run("run", "-ldflags", fmt.Sprintf(`-X "main.extern=%s"`, buf.String()), tg.path("main.go"))
  1347  	if tg.stderr.String() != buf.String() {
  1348  		t.Errorf("strings differ")
  1349  	}
  1350  }
  1351  
  1352  func TestGoTestDashCDashOControlsBinaryLocation(t *testing.T) {
  1353  	skipIfGccgo(t, "gccgo has no standard packages")
  1354  	tooSlow(t, "compiles and links a test binary")
  1355  
  1356  	tg := testgo(t)
  1357  	defer tg.cleanup()
  1358  	tg.parallel()
  1359  	tg.makeTempdir()
  1360  	tg.run("test", "-c", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
  1361  	tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -c -o myerrors.test did not create myerrors.test")
  1362  }
  1363  
  1364  func TestGoTestDashOWritesBinary(t *testing.T) {
  1365  	skipIfGccgo(t, "gccgo has no standard packages")
  1366  	tooSlow(t, "compiles and runs a test binary")
  1367  
  1368  	tg := testgo(t)
  1369  	defer tg.cleanup()
  1370  	tg.parallel()
  1371  	tg.makeTempdir()
  1372  	tg.run("test", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
  1373  	tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -o myerrors.test did not create myerrors.test")
  1374  }
  1375  
  1376  // Issue 4515.
  1377  func TestInstallWithTags(t *testing.T) {
  1378  	tooSlow(t, "compiles and links binaries")
  1379  
  1380  	tg := testgo(t)
  1381  	defer tg.cleanup()
  1382  	tg.parallel()
  1383  	tg.tempDir("bin")
  1384  	tg.tempFile("src/example/a/main.go", `package main
  1385  		func main() {}`)
  1386  	tg.tempFile("src/example/b/main.go", `// +build mytag
  1387  
  1388  		package main
  1389  		func main() {}`)
  1390  	tg.setenv("GOPATH", tg.path("."))
  1391  	tg.run("install", "-tags", "mytag", "example/a", "example/b")
  1392  	tg.wantExecutable(tg.path("bin/a"+exeSuffix), "go install example/a example/b did not install binaries")
  1393  	tg.wantExecutable(tg.path("bin/b"+exeSuffix), "go install example/a example/b did not install binaries")
  1394  	tg.must(os.Remove(tg.path("bin/a" + exeSuffix)))
  1395  	tg.must(os.Remove(tg.path("bin/b" + exeSuffix)))
  1396  	tg.run("install", "-tags", "mytag", "example/...")
  1397  	tg.wantExecutable(tg.path("bin/a"+exeSuffix), "go install example/... did not install binaries")
  1398  	tg.wantExecutable(tg.path("bin/b"+exeSuffix), "go install example/... did not install binaries")
  1399  	tg.run("list", "-tags", "mytag", "example/b...")
  1400  	if strings.TrimSpace(tg.getStdout()) != "example/b" {
  1401  		t.Error("go list example/b did not find example/b")
  1402  	}
  1403  }
  1404  
  1405  // Issue 17451, 17662.
  1406  func TestSymlinkWarning(t *testing.T) {
  1407  	tg := testgo(t)
  1408  	defer tg.cleanup()
  1409  	tg.parallel()
  1410  	tg.makeTempdir()
  1411  	tg.setenv("GOPATH", tg.path("."))
  1412  
  1413  	tg.tempDir("src/example/xx")
  1414  	tg.tempDir("yy/zz")
  1415  	tg.tempFile("yy/zz/zz.go", "package zz\n")
  1416  	if err := os.Symlink(tg.path("yy"), tg.path("src/example/xx/yy")); err != nil {
  1417  		t.Skipf("symlink failed: %v", err)
  1418  	}
  1419  	tg.run("list", "example/xx/z...")
  1420  	tg.grepStdoutNot(".", "list should not have matched anything")
  1421  	tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages")
  1422  	tg.grepStderrNot("symlink", "list should not have reported symlink")
  1423  
  1424  	tg.run("list", "example/xx/...")
  1425  	tg.grepStdoutNot(".", "list should not have matched anything")
  1426  	tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages")
  1427  	tg.grepStderr("ignoring symlink", "list should have reported symlink")
  1428  }
  1429  
  1430  func TestCgoShowsFullPathNames(t *testing.T) {
  1431  	testenv.MustHaveCGO(t)
  1432  
  1433  	tg := testgo(t)
  1434  	defer tg.cleanup()
  1435  	tg.parallel()
  1436  	tg.tempFile("src/x/y/dirname/foo.go", `
  1437  		package foo
  1438  		import "C"
  1439  		func f() {`)
  1440  	tg.setenv("GOPATH", tg.path("."))
  1441  	tg.runFail("build", "x/y/dirname")
  1442  	tg.grepBoth("x/y/dirname", "error did not use full path")
  1443  }
  1444  
  1445  func TestCgoHandlesWlORIGIN(t *testing.T) {
  1446  	tooSlow(t, "compiles cgo files")
  1447  	testenv.MustHaveCGO(t)
  1448  
  1449  	tg := testgo(t)
  1450  	defer tg.cleanup()
  1451  	tg.parallel()
  1452  	tg.tempFile("src/origin/origin.go", `package origin
  1453  		// #cgo !darwin,!windows LDFLAGS: -Wl,-rpath,$ORIGIN
  1454  		// void f(void) {}
  1455  		import "C"
  1456  		func f() { C.f() }`)
  1457  	tg.setenv("GOPATH", tg.path("."))
  1458  	tg.run("build", "origin")
  1459  }
  1460  
  1461  func TestCgoPkgConfig(t *testing.T) {
  1462  	tooSlow(t, "compiles cgo files")
  1463  	testenv.MustHaveCGO(t)
  1464  
  1465  	tg := testgo(t)
  1466  	defer tg.cleanup()
  1467  	tg.parallel()
  1468  
  1469  	tg.run("env", "PKG_CONFIG")
  1470  	pkgConfig := strings.TrimSpace(tg.getStdout())
  1471  	testenv.MustHaveExecPath(t, pkgConfig)
  1472  	if out, err := testenv.Command(t, pkgConfig, "--atleast-pkgconfig-version", "0.24").CombinedOutput(); err != nil {
  1473  		t.Skipf("%s --atleast-pkgconfig-version 0.24: %v\n%s", pkgConfig, err, out)
  1474  	}
  1475  
  1476  	// OpenBSD's pkg-config is strict about whitespace and only
  1477  	// supports backslash-escaped whitespace. It does not support
  1478  	// quotes, which the normal freedesktop.org pkg-config does
  1479  	// support. See https://man.openbsd.org/pkg-config.1
  1480  	tg.tempFile("foo.pc", `
  1481  Name: foo
  1482  Description: The foo library
  1483  Version: 1.0.0
  1484  Cflags: -Dhello=10 -Dworld=+32 -DDEFINED_FROM_PKG_CONFIG=hello\ world
  1485  `)
  1486  	tg.tempFile("foo.go", `package main
  1487  
  1488  /*
  1489  #cgo pkg-config: foo
  1490  int value() {
  1491  	return DEFINED_FROM_PKG_CONFIG;
  1492  }
  1493  */
  1494  import "C"
  1495  import "os"
  1496  
  1497  func main() {
  1498  	if C.value() != 42 {
  1499  		println("value() =", C.value(), "wanted 42")
  1500  		os.Exit(1)
  1501  	}
  1502  }
  1503  `)
  1504  	tg.setenv("PKG_CONFIG_PATH", tg.path("."))
  1505  	tg.run("run", tg.path("foo.go"))
  1506  
  1507  	// test for ldflags
  1508  	tg.tempFile("bar.pc", `
  1509  Name: bar
  1510  Description: The bar library
  1511  Version: 1.0.0
  1512  Libs: -Wl,-rpath=/path\ with\ spaces/bin
  1513  `)
  1514  	tg.tempFile("bar.go", `package main
  1515  /*
  1516  #cgo pkg-config: bar
  1517  */
  1518  import "C"
  1519  func main() {}
  1520  `)
  1521  	tg.run("run", tg.path("bar.go"))
  1522  }
  1523  
  1524  func TestListTemplateContextFunction(t *testing.T) {
  1525  	t.Parallel()
  1526  	for _, tt := range []struct {
  1527  		v    string
  1528  		want string
  1529  	}{
  1530  		{"GOARCH", runtime.GOARCH},
  1531  		{"GOOS", runtime.GOOS},
  1532  		{"GOROOT", testGOROOT},
  1533  		{"GOPATH", os.Getenv("GOPATH")},
  1534  		{"CgoEnabled", ""},
  1535  		{"UseAllFiles", ""},
  1536  		{"Compiler", ""},
  1537  		{"BuildTags", ""},
  1538  		{"ReleaseTags", ""},
  1539  		{"InstallSuffix", ""},
  1540  	} {
  1541  		tt := tt
  1542  		t.Run(tt.v, func(t *testing.T) {
  1543  			tg := testgo(t)
  1544  			tg.parallel()
  1545  			defer tg.cleanup()
  1546  			tmpl := "{{context." + tt.v + "}}"
  1547  			tg.run("list", "-f", tmpl)
  1548  			if tt.want == "" {
  1549  				return
  1550  			}
  1551  			if got := strings.TrimSpace(tg.getStdout()); got != tt.want {
  1552  				t.Errorf("go list -f %q: got %q; want %q", tmpl, got, tt.want)
  1553  			}
  1554  		})
  1555  	}
  1556  }
  1557  
  1558  // Test that you cannot use a local import in a package
  1559  // accessed by a non-local import (found in a GOPATH/GOROOT).
  1560  // See golang.org/issue/17475.
  1561  func TestImportLocal(t *testing.T) {
  1562  	tooSlow(t, "builds a lot of sequential packages")
  1563  
  1564  	tg := testgo(t)
  1565  	tg.parallel()
  1566  	defer tg.cleanup()
  1567  
  1568  	tg.tempFile("src/dir/x/x.go", `package x
  1569  		var X int
  1570  	`)
  1571  	tg.setenv("GOPATH", tg.path("."))
  1572  	tg.run("build", "dir/x")
  1573  
  1574  	// Ordinary import should work.
  1575  	tg.tempFile("src/dir/p0/p.go", `package p0
  1576  		import "dir/x"
  1577  		var _ = x.X
  1578  	`)
  1579  	tg.run("build", "dir/p0")
  1580  
  1581  	// Relative import should not.
  1582  	tg.tempFile("src/dir/p1/p.go", `package p1
  1583  		import "../x"
  1584  		var _ = x.X
  1585  	`)
  1586  	tg.runFail("build", "dir/p1")
  1587  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1588  
  1589  	// ... even in a test.
  1590  	tg.tempFile("src/dir/p2/p.go", `package p2
  1591  	`)
  1592  	tg.tempFile("src/dir/p2/p_test.go", `package p2
  1593  		import "../x"
  1594  		import "testing"
  1595  		var _ = x.X
  1596  		func TestFoo(t *testing.T) {}
  1597  	`)
  1598  	tg.run("build", "dir/p2")
  1599  	tg.runFail("test", "dir/p2")
  1600  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1601  
  1602  	// ... even in an xtest.
  1603  	tg.tempFile("src/dir/p2/p_test.go", `package p2_test
  1604  		import "../x"
  1605  		import "testing"
  1606  		var _ = x.X
  1607  		func TestFoo(t *testing.T) {}
  1608  	`)
  1609  	tg.run("build", "dir/p2")
  1610  	tg.runFail("test", "dir/p2")
  1611  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1612  
  1613  	// Relative import starting with ./ should not work either.
  1614  	tg.tempFile("src/dir/d.go", `package dir
  1615  		import "./x"
  1616  		var _ = x.X
  1617  	`)
  1618  	tg.runFail("build", "dir")
  1619  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1620  
  1621  	// ... even in a test.
  1622  	tg.tempFile("src/dir/d.go", `package dir
  1623  	`)
  1624  	tg.tempFile("src/dir/d_test.go", `package dir
  1625  		import "./x"
  1626  		import "testing"
  1627  		var _ = x.X
  1628  		func TestFoo(t *testing.T) {}
  1629  	`)
  1630  	tg.run("build", "dir")
  1631  	tg.runFail("test", "dir")
  1632  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1633  
  1634  	// ... even in an xtest.
  1635  	tg.tempFile("src/dir/d_test.go", `package dir_test
  1636  		import "./x"
  1637  		import "testing"
  1638  		var _ = x.X
  1639  		func TestFoo(t *testing.T) {}
  1640  	`)
  1641  	tg.run("build", "dir")
  1642  	tg.runFail("test", "dir")
  1643  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1644  
  1645  	// Relative import plain ".." should not work.
  1646  	tg.tempFile("src/dir/x/y/y.go", `package dir
  1647  		import ".."
  1648  		var _ = x.X
  1649  	`)
  1650  	tg.runFail("build", "dir/x/y")
  1651  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1652  
  1653  	// ... even in a test.
  1654  	tg.tempFile("src/dir/x/y/y.go", `package y
  1655  	`)
  1656  	tg.tempFile("src/dir/x/y/y_test.go", `package y
  1657  		import ".."
  1658  		import "testing"
  1659  		var _ = x.X
  1660  		func TestFoo(t *testing.T) {}
  1661  	`)
  1662  	tg.run("build", "dir/x/y")
  1663  	tg.runFail("test", "dir/x/y")
  1664  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1665  
  1666  	// ... even in an x test.
  1667  	tg.tempFile("src/dir/x/y/y_test.go", `package y_test
  1668  		import ".."
  1669  		import "testing"
  1670  		var _ = x.X
  1671  		func TestFoo(t *testing.T) {}
  1672  	`)
  1673  	tg.run("build", "dir/x/y")
  1674  	tg.runFail("test", "dir/x/y")
  1675  	tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
  1676  
  1677  	// Relative import "." should not work.
  1678  	tg.tempFile("src/dir/x/xx.go", `package x
  1679  		import "."
  1680  		var _ = x.X
  1681  	`)
  1682  	tg.runFail("build", "dir/x")
  1683  	tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
  1684  
  1685  	// ... even in a test.
  1686  	tg.tempFile("src/dir/x/xx.go", `package x
  1687  	`)
  1688  	tg.tempFile("src/dir/x/xx_test.go", `package x
  1689  		import "."
  1690  		import "testing"
  1691  		var _ = x.X
  1692  		func TestFoo(t *testing.T) {}
  1693  	`)
  1694  	tg.run("build", "dir/x")
  1695  	tg.runFail("test", "dir/x")
  1696  	tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
  1697  
  1698  	// ... even in an xtest.
  1699  	tg.tempFile("src/dir/x/xx.go", `package x
  1700  	`)
  1701  	tg.tempFile("src/dir/x/xx_test.go", `package x_test
  1702  		import "."
  1703  		import "testing"
  1704  		var _ = x.X
  1705  		func TestFoo(t *testing.T) {}
  1706  	`)
  1707  	tg.run("build", "dir/x")
  1708  	tg.runFail("test", "dir/x")
  1709  	tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
  1710  }
  1711  
  1712  func TestGoInstallPkgdir(t *testing.T) {
  1713  	skipIfGccgo(t, "gccgo has no standard packages")
  1714  	tooSlow(t, "builds a package with cgo dependencies")
  1715  	// Only the stdlib packages that use cgo have install
  1716  	// targets, (we're using net below) so cgo is required
  1717  	// for the install.
  1718  	testenv.MustHaveCGO(t)
  1719  
  1720  	tg := testgo(t)
  1721  	tg.parallel()
  1722  	tg.setenv("GODEBUG", "installgoroot=all")
  1723  	defer tg.cleanup()
  1724  	tg.makeTempdir()
  1725  	pkg := tg.path(".")
  1726  	tg.run("install", "-pkgdir", pkg, "net")
  1727  	tg.mustExist(filepath.Join(pkg, "net.a"))
  1728  	tg.mustNotExist(filepath.Join(pkg, "runtime/cgo.a"))
  1729  }
  1730  
  1731  // For issue 14337.
  1732  func TestParallelTest(t *testing.T) {
  1733  	tooSlow(t, "links and runs test binaries")
  1734  
  1735  	tg := testgo(t)
  1736  	tg.parallel()
  1737  	defer tg.cleanup()
  1738  	tg.makeTempdir()
  1739  	const testSrc = `package package_test
  1740  		import (
  1741  			"testing"
  1742  		)
  1743  		func TestTest(t *testing.T) {
  1744  		}`
  1745  	tg.tempFile("src/p1/p1_test.go", strings.Replace(testSrc, "package_test", "p1_test", 1))
  1746  	tg.tempFile("src/p2/p2_test.go", strings.Replace(testSrc, "package_test", "p2_test", 1))
  1747  	tg.tempFile("src/p3/p3_test.go", strings.Replace(testSrc, "package_test", "p3_test", 1))
  1748  	tg.tempFile("src/p4/p4_test.go", strings.Replace(testSrc, "package_test", "p4_test", 1))
  1749  	tg.setenv("GOPATH", tg.path("."))
  1750  	tg.run("test", "-p=4", "p1", "p2", "p3", "p4")
  1751  }
  1752  
  1753  func TestBinaryOnlyPackages(t *testing.T) {
  1754  	tooSlow(t, "compiles several packages sequentially")
  1755  
  1756  	tg := testgo(t)
  1757  	defer tg.cleanup()
  1758  	tg.parallel()
  1759  	tg.makeTempdir()
  1760  	tg.setenv("GOPATH", tg.path("."))
  1761  
  1762  	tg.tempFile("src/p1/p1.go", `//go:binary-only-package
  1763  
  1764  		package p1
  1765  	`)
  1766  	tg.wantStale("p1", "binary-only packages are no longer supported", "p1 is binary-only, and this message should always be printed")
  1767  	tg.runFail("install", "p1")
  1768  	tg.grepStderr("binary-only packages are no longer supported", "did not report attempt to compile binary-only package")
  1769  
  1770  	tg.tempFile("src/p1/p1.go", `
  1771  		package p1
  1772  		import "fmt"
  1773  		func F(b bool) { fmt.Printf("hello from p1\n"); if b { F(false) } }
  1774  	`)
  1775  	tg.run("install", "p1")
  1776  	os.Remove(tg.path("src/p1/p1.go"))
  1777  	tg.mustNotExist(tg.path("src/p1/p1.go"))
  1778  
  1779  	tg.tempFile("src/p2/p2.go", `//go:binary-only-packages-are-not-great
  1780  
  1781  		package p2
  1782  		import "p1"
  1783  		func F() { p1.F(true) }
  1784  	`)
  1785  	tg.runFail("install", "p2")
  1786  	tg.grepStderr("no Go files", "did not complain about missing sources")
  1787  
  1788  	tg.tempFile("src/p1/missing.go", `//go:binary-only-package
  1789  
  1790  		package p1
  1791  		import _ "fmt"
  1792  		func G()
  1793  	`)
  1794  	tg.wantStale("p1", "binary-only package", "should NOT want to rebuild p1 (first)")
  1795  	tg.runFail("install", "p2")
  1796  	tg.grepStderr("p1: binary-only packages are no longer supported", "did not report error for binary-only p1")
  1797  
  1798  	tg.run("list", "-deps", "-f", "{{.ImportPath}}: {{.BinaryOnly}}", "p2")
  1799  	tg.grepStdout("p1: true", "p1 not listed as BinaryOnly")
  1800  	tg.grepStdout("p2: false", "p2 listed as BinaryOnly")
  1801  }
  1802  
  1803  // Issue 16050 and 21884.
  1804  func TestLinkSysoFiles(t *testing.T) {
  1805  	if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
  1806  		t.Skip("not linux/amd64")
  1807  	}
  1808  
  1809  	tg := testgo(t)
  1810  	defer tg.cleanup()
  1811  	tg.parallel()
  1812  	tg.tempDir("src/syso")
  1813  	tg.tempFile("src/syso/a.syso", ``)
  1814  	tg.tempFile("src/syso/b.go", `package syso`)
  1815  	tg.setenv("GOPATH", tg.path("."))
  1816  
  1817  	// We should see the .syso file regardless of the setting of
  1818  	// CGO_ENABLED.
  1819  
  1820  	tg.setenv("CGO_ENABLED", "1")
  1821  	tg.run("list", "-f", "{{.SysoFiles}}", "syso")
  1822  	tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=1")
  1823  
  1824  	tg.setenv("CGO_ENABLED", "0")
  1825  	tg.run("list", "-f", "{{.SysoFiles}}", "syso")
  1826  	tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=0")
  1827  
  1828  	tg.setenv("CGO_ENABLED", "1")
  1829  	tg.run("list", "-msan", "-f", "{{.SysoFiles}}", "syso")
  1830  	tg.grepStdoutNot("a.syso", "unexpected syso file with -msan")
  1831  }
  1832  
  1833  // Issue 16120.
  1834  func TestGenerateUsesBuildContext(t *testing.T) {
  1835  	if runtime.GOOS == "windows" {
  1836  		t.Skip("this test won't run under Windows")
  1837  	}
  1838  
  1839  	tg := testgo(t)
  1840  	defer tg.cleanup()
  1841  	tg.parallel()
  1842  	tg.tempDir("src/gen")
  1843  	tg.tempFile("src/gen/gen.go", "package gen\n//go:generate echo $GOOS $GOARCH\n")
  1844  	tg.setenv("GOPATH", tg.path("."))
  1845  
  1846  	tg.setenv("GOOS", "linux")
  1847  	tg.setenv("GOARCH", "amd64")
  1848  	tg.run("generate", "gen")
  1849  	tg.grepStdout("linux amd64", "unexpected GOOS/GOARCH combination")
  1850  
  1851  	tg.setenv("GOOS", "darwin")
  1852  	tg.setenv("GOARCH", "arm64")
  1853  	tg.run("generate", "gen")
  1854  	tg.grepStdout("darwin arm64", "unexpected GOOS/GOARCH combination")
  1855  }
  1856  
  1857  func TestGoEnv(t *testing.T) {
  1858  	tg := testgo(t)
  1859  	tg.parallel()
  1860  	defer tg.cleanup()
  1861  	tg.setenv("GOOS", "freebsd") // to avoid invalid pair errors
  1862  	tg.setenv("GOARCH", "arm")
  1863  	tg.run("env", "GOARCH")
  1864  	tg.grepStdout("^arm$", "GOARCH not honored")
  1865  
  1866  	tg.run("env", "GCCGO")
  1867  	tg.grepStdout(".", "GCCGO unexpectedly empty")
  1868  
  1869  	tg.run("env", "CGO_CFLAGS")
  1870  	tg.grepStdout(".", "default CGO_CFLAGS unexpectedly empty")
  1871  
  1872  	tg.setenv("CGO_CFLAGS", "-foobar")
  1873  	tg.run("env", "CGO_CFLAGS")
  1874  	tg.grepStdout("^-foobar$", "CGO_CFLAGS not honored")
  1875  
  1876  	tg.setenv("CC", "gcc -fmust -fgo -ffaster")
  1877  	tg.run("env", "CC")
  1878  	tg.grepStdout("gcc", "CC not found")
  1879  	tg.run("env", "GOGCCFLAGS")
  1880  	tg.grepStdout("-ffaster", "CC arguments not found")
  1881  
  1882  	tg.run("env", "GOVERSION")
  1883  	envVersion := strings.TrimSpace(tg.stdout.String())
  1884  
  1885  	tg.run("version")
  1886  	cmdVersion := strings.TrimSpace(tg.stdout.String())
  1887  
  1888  	// If 'go version' is "go version <version> <goos>/<goarch>", then
  1889  	// 'go env GOVERSION' is just "<version>".
  1890  	if cmdVersion == envVersion || !strings.Contains(cmdVersion, envVersion) {
  1891  		t.Fatalf("'go env GOVERSION' %q should be a shorter substring of 'go version' %q", envVersion, cmdVersion)
  1892  	}
  1893  }
  1894  
  1895  const (
  1896  	noMatchesPattern = `(?m)^ok.*\[no tests to run\]`
  1897  	okPattern        = `(?m)^ok`
  1898  )
  1899  
  1900  // Issue 18044.
  1901  func TestLdBindNow(t *testing.T) {
  1902  	tg := testgo(t)
  1903  	defer tg.cleanup()
  1904  	tg.parallel()
  1905  	tg.setenv("LD_BIND_NOW", "1")
  1906  	tg.run("help")
  1907  }
  1908  
  1909  // Issue 18225.
  1910  // This is really a cmd/asm issue but this is a convenient place to test it.
  1911  func TestConcurrentAsm(t *testing.T) {
  1912  	skipIfGccgo(t, "gccgo does not use cmd/asm")
  1913  	tg := testgo(t)
  1914  	defer tg.cleanup()
  1915  	tg.parallel()
  1916  	asm := `DATA ·constants<>+0x0(SB)/8,$0
  1917  GLOBL ·constants<>(SB),8,$8
  1918  `
  1919  	tg.tempFile("go/src/p/a.s", asm)
  1920  	tg.tempFile("go/src/p/b.s", asm)
  1921  	tg.tempFile("go/src/p/p.go", `package p`)
  1922  	tg.setenv("GOPATH", tg.path("go"))
  1923  	tg.run("build", "p")
  1924  }
  1925  
  1926  // Issue 18975.
  1927  func TestFFLAGS(t *testing.T) {
  1928  	testenv.MustHaveCGO(t)
  1929  
  1930  	tg := testgo(t)
  1931  	defer tg.cleanup()
  1932  	tg.parallel()
  1933  
  1934  	tg.tempFile("p/src/p/main.go", `package main
  1935  		// #cgo FFLAGS: -no-such-fortran-flag
  1936  		import "C"
  1937  		func main() {}
  1938  	`)
  1939  	tg.tempFile("p/src/p/a.f", `! comment`)
  1940  	tg.setenv("GOPATH", tg.path("p"))
  1941  
  1942  	// This should normally fail because we are passing an unknown flag,
  1943  	// but issue #19080 points to Fortran compilers that succeed anyhow.
  1944  	// To work either way we call doRun directly rather than run or runFail.
  1945  	tg.doRun([]string{"build", "-x", "p"})
  1946  
  1947  	tg.grepStderr("no-such-fortran-flag", `missing expected "-no-such-fortran-flag"`)
  1948  }
  1949  
  1950  // Issue 19198.
  1951  // This is really a cmd/link issue but this is a convenient place to test it.
  1952  func TestDuplicateGlobalAsmSymbols(t *testing.T) {
  1953  	skipIfGccgo(t, "gccgo does not use cmd/asm")
  1954  	tooSlow(t, "links a binary with cgo dependencies")
  1955  	if runtime.GOARCH != "386" && runtime.GOARCH != "amd64" {
  1956  		t.Skipf("skipping test on %s", runtime.GOARCH)
  1957  	}
  1958  	testenv.MustHaveCGO(t)
  1959  
  1960  	tg := testgo(t)
  1961  	defer tg.cleanup()
  1962  	tg.parallel()
  1963  
  1964  	asm := `
  1965  #include "textflag.h"
  1966  
  1967  DATA sym<>+0x0(SB)/8,$0
  1968  GLOBL sym<>(SB),(NOPTR+RODATA),$8
  1969  
  1970  TEXT ·Data(SB),NOSPLIT,$0
  1971  	MOVB sym<>(SB), AX
  1972  	MOVB AX, ret+0(FP)
  1973  	RET
  1974  `
  1975  	tg.tempFile("go/src/a/a.s", asm)
  1976  	tg.tempFile("go/src/a/a.go", `package a; func Data() uint8`)
  1977  	tg.tempFile("go/src/b/b.s", asm)
  1978  	tg.tempFile("go/src/b/b.go", `package b; func Data() uint8`)
  1979  	tg.tempFile("go/src/p/p.go", `
  1980  package main
  1981  import "a"
  1982  import "b"
  1983  import "C"
  1984  func main() {
  1985  	_ = a.Data() + b.Data()
  1986  }
  1987  `)
  1988  	tg.setenv("GOPATH", tg.path("go"))
  1989  	exe := tg.path("p.exe")
  1990  	tg.creatingTemp(exe)
  1991  	tg.run("build", "-o", exe, "p")
  1992  }
  1993  
  1994  func copyFile(src, dst string, perm fs.FileMode) error {
  1995  	sf, err := os.Open(src)
  1996  	if err != nil {
  1997  		return err
  1998  	}
  1999  	defer sf.Close()
  2000  
  2001  	df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
  2002  	if err != nil {
  2003  		return err
  2004  	}
  2005  
  2006  	_, err = io.Copy(df, sf)
  2007  	err2 := df.Close()
  2008  	if err != nil {
  2009  		return err
  2010  	}
  2011  	return err2
  2012  }
  2013  
  2014  func TestNeedVersion(t *testing.T) {
  2015  	skipIfGccgo(t, "gccgo does not use cmd/compile")
  2016  	tg := testgo(t)
  2017  	defer tg.cleanup()
  2018  	tg.parallel()
  2019  	tg.tempFile("goversion.go", `package main; func main() {}`)
  2020  	path := tg.path("goversion.go")
  2021  	tg.setenv("TESTGO_TOOLCHAIN_VERSION", "go1.testgo")
  2022  	tg.runFail("run", path)
  2023  	tg.grepStderr("compile", "does not match go tool version")
  2024  }
  2025  
  2026  func TestBuildmodePIE(t *testing.T) {
  2027  	tooSlow(t, "links binaries")
  2028  
  2029  	if !platform.BuildModeSupported(runtime.Compiler, "pie", runtime.GOOS, runtime.GOARCH) {
  2030  		t.Skipf("skipping test because buildmode=pie is not supported on %s/%s", runtime.GOOS, runtime.GOARCH)
  2031  	}
  2032  	// Skip on alpine until https://go.dev/issues/54354 resolved.
  2033  	if strings.HasSuffix(testenv.Builder(), "-alpine") {
  2034  		t.Skip("skipping PIE tests on alpine; see https://go.dev/issues/54354")
  2035  	}
  2036  	t.Run("non-cgo", func(t *testing.T) {
  2037  		testBuildmodePIE(t, false, true)
  2038  	})
  2039  	t.Run("cgo", func(t *testing.T) {
  2040  		testenv.MustHaveCGO(t)
  2041  		testBuildmodePIE(t, true, true)
  2042  	})
  2043  }
  2044  
  2045  func TestWindowsDefaultBuildmodIsPIE(t *testing.T) {
  2046  	if runtime.GOOS != "windows" {
  2047  		t.Skip("skipping windows only test")
  2048  	}
  2049  	tooSlow(t, "links binaries")
  2050  
  2051  	t.Run("non-cgo", func(t *testing.T) {
  2052  		testBuildmodePIE(t, false, false)
  2053  	})
  2054  	t.Run("cgo", func(t *testing.T) {
  2055  		testenv.MustHaveCGO(t)
  2056  		testBuildmodePIE(t, true, false)
  2057  	})
  2058  }
  2059  
  2060  func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) {
  2061  	tg := testgo(t)
  2062  	defer tg.cleanup()
  2063  	tg.parallel()
  2064  
  2065  	var s string
  2066  	if useCgo {
  2067  		s = `import "C";`
  2068  	}
  2069  	tg.tempFile("main.go", fmt.Sprintf(`package main;%s func main() { print("hello") }`, s))
  2070  	src := tg.path("main.go")
  2071  	obj := tg.path("main.exe")
  2072  	args := []string{"build"}
  2073  	if setBuildmodeToPIE {
  2074  		args = append(args, "-buildmode=pie")
  2075  	}
  2076  	args = append(args, "-o", obj, src)
  2077  	tg.run(args...)
  2078  
  2079  	switch runtime.GOOS {
  2080  	case "linux", "android", "freebsd":
  2081  		f, err := elf.Open(obj)
  2082  		if err != nil {
  2083  			t.Fatal(err)
  2084  		}
  2085  		defer f.Close()
  2086  		if f.Type != elf.ET_DYN {
  2087  			t.Errorf("PIE type must be ET_DYN, but %s", f.Type)
  2088  		}
  2089  	case "darwin", "ios":
  2090  		f, err := macho.Open(obj)
  2091  		if err != nil {
  2092  			t.Fatal(err)
  2093  		}
  2094  		defer f.Close()
  2095  		if f.Flags&macho.FlagDyldLink == 0 {
  2096  			t.Error("PIE must have DyldLink flag, but not")
  2097  		}
  2098  		if f.Flags&macho.FlagPIE == 0 {
  2099  			t.Error("PIE must have PIE flag, but not")
  2100  		}
  2101  	case "windows":
  2102  		f, err := pe.Open(obj)
  2103  		if err != nil {
  2104  			t.Fatal(err)
  2105  		}
  2106  		defer f.Close()
  2107  		if f.Section(".reloc") == nil {
  2108  			t.Error(".reloc section is not present")
  2109  		}
  2110  		if (f.FileHeader.Characteristics & pe.IMAGE_FILE_RELOCS_STRIPPED) != 0 {
  2111  			t.Error("IMAGE_FILE_RELOCS_STRIPPED flag is set")
  2112  		}
  2113  		var dc uint16
  2114  		switch oh := f.OptionalHeader.(type) {
  2115  		case *pe.OptionalHeader32:
  2116  			dc = oh.DllCharacteristics
  2117  		case *pe.OptionalHeader64:
  2118  			dc = oh.DllCharacteristics
  2119  			if (dc & pe.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) == 0 {
  2120  				t.Error("IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA flag is not set")
  2121  			}
  2122  		default:
  2123  			t.Fatalf("unexpected optional header type of %T", f.OptionalHeader)
  2124  		}
  2125  		if (dc & pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 {
  2126  			t.Error("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag is not set")
  2127  		}
  2128  		if useCgo {
  2129  			// Test that only one symbol is exported (#40795).
  2130  			// PIE binaries don´t require .edata section but unfortunately
  2131  			// binutils doesn´t generate a .reloc section unless there is
  2132  			// at least one symbol exported.
  2133  			// See https://sourceware.org/bugzilla/show_bug.cgi?id=19011
  2134  			section := f.Section(".edata")
  2135  			if section == nil {
  2136  				t.Skip(".edata section is not present")
  2137  			}
  2138  			// TODO: deduplicate this struct from cmd/link/internal/ld/pe.go
  2139  			type IMAGE_EXPORT_DIRECTORY struct {
  2140  				_                 [2]uint32
  2141  				_                 [2]uint16
  2142  				_                 [2]uint32
  2143  				NumberOfFunctions uint32
  2144  				NumberOfNames     uint32
  2145  				_                 [3]uint32
  2146  			}
  2147  			var e IMAGE_EXPORT_DIRECTORY
  2148  			if err := binary.Read(section.Open(), binary.LittleEndian, &e); err != nil {
  2149  				t.Fatalf("binary.Read failed: %v", err)
  2150  			}
  2151  
  2152  			// Only _cgo_dummy_export should be exported
  2153  			if e.NumberOfFunctions != 1 {
  2154  				t.Fatalf("got %d exported functions; want 1", e.NumberOfFunctions)
  2155  			}
  2156  			if e.NumberOfNames != 1 {
  2157  				t.Fatalf("got %d exported names; want 1", e.NumberOfNames)
  2158  			}
  2159  		}
  2160  	default:
  2161  		// testBuildmodePIE opens object files, so it needs to understand the object
  2162  		// file format.
  2163  		t.Skipf("skipping test: test helper does not support %s", runtime.GOOS)
  2164  	}
  2165  
  2166  	out, err := testenv.Command(t, obj).CombinedOutput()
  2167  	if err != nil {
  2168  		t.Fatal(err)
  2169  	}
  2170  
  2171  	if string(out) != "hello" {
  2172  		t.Errorf("got %q; want %q", out, "hello")
  2173  	}
  2174  }
  2175  
  2176  func TestUpxCompression(t *testing.T) {
  2177  	if runtime.GOOS != "linux" ||
  2178  		(runtime.GOARCH != "amd64" && runtime.GOARCH != "386") {
  2179  		t.Skipf("skipping upx test on %s/%s", runtime.GOOS, runtime.GOARCH)
  2180  	}
  2181  
  2182  	testenv.MustHaveExecPath(t, "upx")
  2183  	out, err := testenv.Command(t, "upx", "--version").CombinedOutput()
  2184  	if err != nil {
  2185  		t.Fatalf("upx --version failed: %v", err)
  2186  	}
  2187  
  2188  	// upx --version prints `upx <version>` in the first line of output:
  2189  	//   upx 3.94
  2190  	//   [...]
  2191  	re := regexp.MustCompile(`([[:digit:]]+)\.([[:digit:]]+)`)
  2192  	upxVersion := re.FindStringSubmatch(string(out))
  2193  	if len(upxVersion) != 3 {
  2194  		t.Fatalf("bad upx version string: %s", upxVersion)
  2195  	}
  2196  
  2197  	major, err1 := strconv.Atoi(upxVersion[1])
  2198  	minor, err2 := strconv.Atoi(upxVersion[2])
  2199  	if err1 != nil || err2 != nil {
  2200  		t.Fatalf("bad upx version string: %s", upxVersion[0])
  2201  	}
  2202  
  2203  	// Anything below 3.94 is known not to work with go binaries
  2204  	if (major < 3) || (major == 3 && minor < 94) {
  2205  		t.Skipf("skipping because upx version %v.%v is too old", major, minor)
  2206  	}
  2207  
  2208  	tg := testgo(t)
  2209  	defer tg.cleanup()
  2210  	tg.parallel()
  2211  
  2212  	tg.tempFile("main.go", `package main; import "fmt"; func main() { fmt.Print("hello upx") }`)
  2213  	src := tg.path("main.go")
  2214  	obj := tg.path("main")
  2215  	tg.run("build", "-o", obj, src)
  2216  
  2217  	out, err = testenv.Command(t, "upx", obj).CombinedOutput()
  2218  	if err != nil {
  2219  		t.Logf("executing upx\n%s\n", out)
  2220  		t.Fatalf("upx failed with %v", err)
  2221  	}
  2222  
  2223  	out, err = testenv.Command(t, obj).CombinedOutput()
  2224  	if err != nil {
  2225  		t.Logf("%s", out)
  2226  		t.Fatalf("running compressed go binary failed with error %s", err)
  2227  	}
  2228  	if string(out) != "hello upx" {
  2229  		t.Fatalf("bad output from compressed go binary:\ngot %q; want %q", out, "hello upx")
  2230  	}
  2231  }
  2232  
  2233  var gocacheverify = godebug.New("#gocacheverify")
  2234  
  2235  func TestCacheListStale(t *testing.T) {
  2236  	tooSlow(t, "links a binary")
  2237  	if gocacheverify.Value() == "1" {
  2238  		t.Skip("GODEBUG gocacheverify")
  2239  	}
  2240  
  2241  	tg := testgo(t)
  2242  	defer tg.cleanup()
  2243  	tg.parallel()
  2244  	tg.makeTempdir()
  2245  	tg.setenv("GOCACHE", tg.path("cache"))
  2246  	tg.tempFile("gopath/src/p/p.go", "package p; import _ \"q\"; func F(){}\n")
  2247  	tg.tempFile("gopath/src/q/q.go", "package q; func F(){}\n")
  2248  	tg.tempFile("gopath/src/m/m.go", "package main; import _ \"q\"; func main(){}\n")
  2249  
  2250  	tg.setenv("GOPATH", tg.path("gopath"))
  2251  	tg.run("install", "p", "m")
  2252  	tg.run("list", "-f={{.ImportPath}} {{.Stale}}", "m", "q", "p")
  2253  	tg.grepStdout("^m false", "m should not be stale")
  2254  	tg.grepStdout("^q true", "q should be stale")
  2255  	tg.grepStdout("^p false", "p should not be stale")
  2256  }
  2257  
  2258  func TestCacheCoverage(t *testing.T) {
  2259  	tooSlow(t, "links and runs a test binary with coverage enabled")
  2260  	if gocacheverify.Value() == "1" {
  2261  		t.Skip("GODEBUG gocacheverify")
  2262  	}
  2263  
  2264  	tg := testgo(t)
  2265  	defer tg.cleanup()
  2266  	tg.parallel()
  2267  	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
  2268  	tg.makeTempdir()
  2269  
  2270  	tg.setenv("GOCACHE", tg.path("c1"))
  2271  	tg.run("test", "-cover", "-short", "strings")
  2272  	tg.run("test", "-cover", "-short", "math", "strings")
  2273  }
  2274  
  2275  func TestIssue22588(t *testing.T) {
  2276  	// Don't get confused by stderr coming from tools.
  2277  	tg := testgo(t)
  2278  	defer tg.cleanup()
  2279  	tg.parallel()
  2280  
  2281  	tg.wantNotStale("runtime", "", "must be non-stale to compare staleness under -toolexec")
  2282  
  2283  	if _, err := os.Stat("/usr/bin/time"); err != nil {
  2284  		t.Skip(err)
  2285  	}
  2286  
  2287  	tg.run("list", "-f={{.Stale}}", "runtime")
  2288  	tg.run("list", "-toolexec=/usr/bin/time", "-f={{.Stale}}", "runtime")
  2289  	tg.grepStdout("false", "incorrectly reported runtime as stale")
  2290  }
  2291  
  2292  func TestIssue22531(t *testing.T) {
  2293  	tooSlow(t, "links binaries")
  2294  	if gocacheverify.Value() == "1" {
  2295  		t.Skip("GODEBUG gocacheverify")
  2296  	}
  2297  
  2298  	tg := testgo(t)
  2299  	defer tg.cleanup()
  2300  	tg.parallel()
  2301  	tg.makeTempdir()
  2302  	tg.setenv("GOPATH", tg.tempdir)
  2303  	tg.setenv("GOCACHE", tg.path("cache"))
  2304  	tg.tempFile("src/m/main.go", "package main /* c1 */; func main() {}\n")
  2305  	tg.run("install", "-x", "m")
  2306  	tg.run("list", "-f", "{{.Stale}}", "m")
  2307  	tg.grepStdout("false", "reported m as stale after install")
  2308  	tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix))
  2309  
  2310  	// The link action ID did not include the full main build ID,
  2311  	// even though the full main build ID is written into the
  2312  	// eventual binary. That caused the following install to
  2313  	// be a no-op, thinking the gofmt binary was up-to-date,
  2314  	// even though .Stale could see it was not.
  2315  	tg.tempFile("src/m/main.go", "package main /* c2 */; func main() {}\n")
  2316  	tg.run("install", "-x", "m")
  2317  	tg.run("list", "-f", "{{.Stale}}", "m")
  2318  	tg.grepStdout("false", "reported m as stale after reinstall")
  2319  	tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix))
  2320  }
  2321  
  2322  func TestIssue22596(t *testing.T) {
  2323  	tooSlow(t, "links binaries")
  2324  	if gocacheverify.Value() == "1" {
  2325  		t.Skip("GODEBUG gocacheverify")
  2326  	}
  2327  
  2328  	tg := testgo(t)
  2329  	defer tg.cleanup()
  2330  	tg.parallel()
  2331  	tg.makeTempdir()
  2332  	tg.setenv("GOCACHE", tg.path("cache"))
  2333  	tg.tempFile("gopath1/src/p/p.go", "package p; func F(){}\n")
  2334  	tg.tempFile("gopath2/src/p/p.go", "package p; func F(){}\n")
  2335  
  2336  	tg.setenv("GOPATH", tg.path("gopath1"))
  2337  	tg.run("list", "-f={{.Target}}", "p")
  2338  	target1 := strings.TrimSpace(tg.getStdout())
  2339  	tg.run("install", "p")
  2340  	tg.wantNotStale("p", "", "p stale after install")
  2341  
  2342  	tg.setenv("GOPATH", tg.path("gopath2"))
  2343  	tg.run("list", "-f={{.Target}}", "p")
  2344  	target2 := strings.TrimSpace(tg.getStdout())
  2345  	tg.must(os.MkdirAll(filepath.Dir(target2), 0777))
  2346  	tg.must(copyFile(target1, target2, 0666))
  2347  	tg.wantStale("p", "build ID mismatch", "p not stale after copy from gopath1")
  2348  	tg.run("install", "p")
  2349  	tg.wantNotStale("p", "", "p stale after install2")
  2350  }
  2351  
  2352  func TestTestCache(t *testing.T) {
  2353  	tooSlow(t, "links and runs test binaries")
  2354  	if gocacheverify.Value() == "1" {
  2355  		t.Skip("GODEBUG gocacheverify")
  2356  	}
  2357  
  2358  	tg := testgo(t)
  2359  	defer tg.cleanup()
  2360  	tg.parallel()
  2361  	tg.makeTempdir()
  2362  	tg.setenv("GOPATH", tg.tempdir)
  2363  	tg.setenv("GOCACHE", tg.path("cache"))
  2364  
  2365  	// The -p=1 in the commands below just makes the -x output easier to read.
  2366  
  2367  	t.Log("\n\nINITIAL\n\n")
  2368  
  2369  	tg.tempFile("src/p1/p1.go", "package p1\nvar X =  1\n")
  2370  	tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\nvar X = 1\n")
  2371  	tg.tempFile("src/t/t1/t1_test.go", "package t\nimport \"testing\"\nfunc Test1(*testing.T) {}\n")
  2372  	tg.tempFile("src/t/t2/t2_test.go", "package t\nimport _ \"p1\"\nimport \"testing\"\nfunc Test2(*testing.T) {}\n")
  2373  	tg.tempFile("src/t/t3/t3_test.go", "package t\nimport \"p1\"\nimport \"testing\"\nfunc Test3(t *testing.T) {t.Log(p1.X)}\n")
  2374  	tg.tempFile("src/t/t4/t4_test.go", "package t\nimport \"p2\"\nimport \"testing\"\nfunc Test4(t *testing.T) {t.Log(p2.X)}")
  2375  	tg.run("test", "-x", "-v", "-short", "t/...")
  2376  
  2377  	t.Log("\n\nREPEAT\n\n")
  2378  
  2379  	tg.run("test", "-x", "-v", "-short", "t/...")
  2380  	tg.grepStdout(`ok  \tt/t1\t\(cached\)`, "did not cache t1")
  2381  	tg.grepStdout(`ok  \tt/t2\t\(cached\)`, "did not cache t2")
  2382  	tg.grepStdout(`ok  \tt/t3\t\(cached\)`, "did not cache t3")
  2383  	tg.grepStdout(`ok  \tt/t4\t\(cached\)`, "did not cache t4")
  2384  	tg.grepStderrNot(`[\\/](compile|gccgo) `, "incorrectly ran compiler")
  2385  	tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker")
  2386  	tg.grepStderrNot(`p[0-9]\.test`, "incorrectly ran test")
  2387  
  2388  	t.Log("\n\nCOMMENT\n\n")
  2389  
  2390  	// Changing the program text without affecting the compiled package
  2391  	// should result in the package being rebuilt but nothing more.
  2392  	tg.tempFile("src/p1/p1.go", "package p1\nvar X = 01\n")
  2393  	tg.run("test", "-p=1", "-x", "-v", "-short", "t/...")
  2394  	tg.grepStdout(`ok  \tt/t1\t\(cached\)`, "did not cache t1")
  2395  	tg.grepStdout(`ok  \tt/t2\t\(cached\)`, "did not cache t2")
  2396  	tg.grepStdout(`ok  \tt/t3\t\(cached\)`, "did not cache t3")
  2397  	tg.grepStdout(`ok  \tt/t4\t\(cached\)`, "did not cache t4")
  2398  	tg.grepStderrNot(`([\\/](compile|gccgo) ).*t[0-9]_test\.go`, "incorrectly ran compiler")
  2399  	tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker")
  2400  	tg.grepStderrNot(`t[0-9]\.test.*test\.short`, "incorrectly ran test")
  2401  
  2402  	t.Log("\n\nCHANGE\n\n")
  2403  
  2404  	// Changing the actual package should have limited effects.
  2405  	tg.tempFile("src/p1/p1.go", "package p1\nvar X = 02\n")
  2406  	tg.run("test", "-p=1", "-x", "-v", "-short", "t/...")
  2407  
  2408  	// p2 should have been rebuilt.
  2409  	tg.grepStderr(`([\\/]compile|gccgo).*p2.go`, "did not recompile p2")
  2410  
  2411  	// t1 does not import anything, should not have been rebuilt.
  2412  	tg.grepStderrNot(`([\\/]compile|gccgo).*t1_test.go`, "incorrectly recompiled t1")
  2413  	tg.grepStderrNot(`([\\/]link|gccgo).*t1_test`, "incorrectly relinked t1_test")
  2414  	tg.grepStdout(`ok  \tt/t1\t\(cached\)`, "did not cache t/t1")
  2415  
  2416  	// t2 imports p1 and must be rebuilt and relinked,
  2417  	// but the change should not have any effect on the test binary,
  2418  	// so the test should not have been rerun.
  2419  	tg.grepStderr(`([\\/]compile|gccgo).*t2_test.go`, "did not recompile t2")
  2420  	tg.grepStderr(`([\\/]link|gccgo).*t2\.test`, "did not relink t2_test")
  2421  	// This check does not currently work with gccgo, as garbage
  2422  	// collection of unused variables is not turned on by default.
  2423  	if runtime.Compiler != "gccgo" {
  2424  		tg.grepStdout(`ok  \tt/t2\t\(cached\)`, "did not cache t/t2")
  2425  	}
  2426  
  2427  	// t3 imports p1, and changing X changes t3's test binary.
  2428  	tg.grepStderr(`([\\/]compile|gccgo).*t3_test.go`, "did not recompile t3")
  2429  	tg.grepStderr(`([\\/]link|gccgo).*t3\.test`, "did not relink t3_test")
  2430  	tg.grepStderr(`t3\.test.*-test.short`, "did not rerun t3_test")
  2431  	tg.grepStdoutNot(`ok  \tt/t3\t\(cached\)`, "reported cached t3_test result")
  2432  
  2433  	// t4 imports p2, but p2 did not change, so t4 should be relinked, not recompiled,
  2434  	// and not rerun.
  2435  	tg.grepStderrNot(`([\\/]compile|gccgo).*t4_test.go`, "incorrectly recompiled t4")
  2436  	tg.grepStderr(`([\\/]link|gccgo).*t4\.test`, "did not relink t4_test")
  2437  	// This check does not currently work with gccgo, as garbage
  2438  	// collection of unused variables is not turned on by default.
  2439  	if runtime.Compiler != "gccgo" {
  2440  		tg.grepStdout(`ok  \tt/t4\t\(cached\)`, "did not cache t/t4")
  2441  	}
  2442  }
  2443  
  2444  func TestTestSkipVetAfterFailedBuild(t *testing.T) {
  2445  	tg := testgo(t)
  2446  	defer tg.cleanup()
  2447  	tg.parallel()
  2448  
  2449  	tg.tempFile("x_test.go", `package x
  2450  		func f() {
  2451  			return 1
  2452  		}
  2453  	`)
  2454  
  2455  	tg.runFail("test", tg.path("x_test.go"))
  2456  	tg.grepStderrNot(`vet`, "vet should be skipped after the failed build")
  2457  }
  2458  
  2459  func TestTestVetRebuild(t *testing.T) {
  2460  	tooSlow(t, "links and runs test binaries")
  2461  
  2462  	tg := testgo(t)
  2463  	defer tg.cleanup()
  2464  	tg.parallel()
  2465  
  2466  	// golang.org/issue/23701.
  2467  	// b_test imports b with augmented method from export_test.go.
  2468  	// b_test also imports a, which imports b.
  2469  	// Must not accidentally see un-augmented b propagate through a to b_test.
  2470  	tg.tempFile("src/a/a.go", `package a
  2471  		import "b"
  2472  		type Type struct{}
  2473  		func (*Type) M() b.T {return 0}
  2474  	`)
  2475  	tg.tempFile("src/b/b.go", `package b
  2476  		type T int
  2477  		type I interface {M() T}
  2478  	`)
  2479  	tg.tempFile("src/b/export_test.go", `package b
  2480  		func (*T) Method() *T { return nil }
  2481  	`)
  2482  	tg.tempFile("src/b/b_test.go", `package b_test
  2483  		import (
  2484  			"testing"
  2485  			"a"
  2486  			. "b"
  2487  		)
  2488  		func TestBroken(t *testing.T) {
  2489  			x := new(T)
  2490  			x.Method()
  2491  			_ = new(a.Type)
  2492  		}
  2493  	`)
  2494  
  2495  	tg.setenv("GOPATH", tg.path("."))
  2496  	tg.run("test", "b")
  2497  	tg.run("vet", "b")
  2498  }
  2499  
  2500  func TestInstallDeps(t *testing.T) {
  2501  	tooSlow(t, "links a binary")
  2502  
  2503  	tg := testgo(t)
  2504  	defer tg.cleanup()
  2505  	tg.parallel()
  2506  	tg.makeTempdir()
  2507  	tg.setenv("GOPATH", tg.tempdir)
  2508  
  2509  	tg.tempFile("src/p1/p1.go", "package p1\nvar X =  1\n")
  2510  	tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\n")
  2511  	tg.tempFile("src/main1/main.go", "package main\nimport _ \"p2\"\nfunc main() {}\n")
  2512  
  2513  	tg.run("list", "-f={{.Target}}", "p1")
  2514  	p1 := strings.TrimSpace(tg.getStdout())
  2515  	tg.run("list", "-f={{.Target}}", "p2")
  2516  	p2 := strings.TrimSpace(tg.getStdout())
  2517  	tg.run("list", "-f={{.Target}}", "main1")
  2518  	main1 := strings.TrimSpace(tg.getStdout())
  2519  
  2520  	tg.run("install", "main1")
  2521  
  2522  	tg.mustExist(main1)
  2523  	tg.mustNotExist(p2)
  2524  	tg.mustNotExist(p1)
  2525  
  2526  	tg.run("install", "p2")
  2527  	tg.mustExist(p2)
  2528  	tg.mustNotExist(p1)
  2529  }
  2530  
  2531  // Issue 22986.
  2532  func TestImportPath(t *testing.T) {
  2533  	tooSlow(t, "links and runs a test binary")
  2534  
  2535  	tg := testgo(t)
  2536  	defer tg.cleanup()
  2537  	tg.parallel()
  2538  
  2539  	tg.tempFile("src/a/a.go", `
  2540  package main
  2541  
  2542  import (
  2543  	"log"
  2544  	p "a/p-1.0"
  2545  )
  2546  
  2547  func main() {
  2548  	if !p.V {
  2549  		log.Fatal("false")
  2550  	}
  2551  }`)
  2552  
  2553  	tg.tempFile("src/a/a_test.go", `
  2554  package main_test
  2555  
  2556  import (
  2557  	p "a/p-1.0"
  2558  	"testing"
  2559  )
  2560  
  2561  func TestV(t *testing.T) {
  2562  	if !p.V {
  2563  		t.Fatal("false")
  2564  	}
  2565  }`)
  2566  
  2567  	tg.tempFile("src/a/p-1.0/p.go", `
  2568  package p
  2569  
  2570  var V = true
  2571  
  2572  func init() {}
  2573  `)
  2574  
  2575  	tg.setenv("GOPATH", tg.path("."))
  2576  	tg.run("build", "-o", tg.path("a.exe"), "a")
  2577  	tg.run("test", "a")
  2578  }
  2579  
  2580  func TestBadCommandLines(t *testing.T) {
  2581  	tg := testgo(t)
  2582  	defer tg.cleanup()
  2583  	tg.parallel()
  2584  
  2585  	tg.tempFile("src/x/x.go", "package x\n")
  2586  	tg.setenv("GOPATH", tg.path("."))
  2587  
  2588  	tg.run("build", "x")
  2589  
  2590  	tg.tempFile("src/x/@y.go", "package x\n")
  2591  	tg.runFail("build", "x")
  2592  	tg.grepStderr("invalid input file name \"@y.go\"", "did not reject @y.go")
  2593  	tg.must(os.Remove(tg.path("src/x/@y.go")))
  2594  
  2595  	tg.tempFile("src/x/-y.go", "package x\n")
  2596  	tg.runFail("build", "x")
  2597  	tg.grepStderr("invalid input file name \"-y.go\"", "did not reject -y.go")
  2598  	tg.must(os.Remove(tg.path("src/x/-y.go")))
  2599  
  2600  	if runtime.Compiler == "gccgo" {
  2601  		tg.runFail("build", "-gccgoflags=all=@x", "x")
  2602  	} else {
  2603  		tg.runFail("build", "-gcflags=all=@x", "x")
  2604  	}
  2605  	tg.grepStderr("invalid command-line argument @x in command", "did not reject @x during exec")
  2606  
  2607  	tg.tempFile("src/@x/x.go", "package x\n")
  2608  	tg.setenv("GOPATH", tg.path("."))
  2609  	tg.runFail("build", "@x")
  2610  	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")
  2611  
  2612  	tg.tempFile("src/@x/y/y.go", "package y\n")
  2613  	tg.setenv("GOPATH", tg.path("."))
  2614  	tg.runFail("build", "@x/y")
  2615  	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")
  2616  
  2617  	tg.tempFile("src/-x/x.go", "package x\n")
  2618  	tg.setenv("GOPATH", tg.path("."))
  2619  	tg.runFail("build", "--", "-x")
  2620  	tg.grepStderr("invalid import path \"-x\"", "did not reject -x import path")
  2621  
  2622  	tg.tempFile("src/-x/y/y.go", "package y\n")
  2623  	tg.setenv("GOPATH", tg.path("."))
  2624  	tg.runFail("build", "--", "-x/y")
  2625  	tg.grepStderr("invalid import path \"-x/y\"", "did not reject -x/y import path")
  2626  }
  2627  
  2628  func TestTwoPkgConfigs(t *testing.T) {
  2629  	testenv.MustHaveCGO(t)
  2630  	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
  2631  		t.Skipf("no shell scripts on %s", runtime.GOOS)
  2632  	}
  2633  	tooSlow(t, "builds a package with cgo dependencies")
  2634  
  2635  	tg := testgo(t)
  2636  	defer tg.cleanup()
  2637  	tg.parallel()
  2638  	tg.tempFile("src/x/a.go", `package x
  2639  		// #cgo pkg-config: --static a
  2640  		import "C"
  2641  	`)
  2642  	tg.tempFile("src/x/b.go", `package x
  2643  		// #cgo pkg-config: --static a
  2644  		import "C"
  2645  	`)
  2646  	tg.tempFile("pkg-config.sh", `#!/bin/sh
  2647  echo $* >>`+tg.path("pkg-config.out"))
  2648  	tg.must(os.Chmod(tg.path("pkg-config.sh"), 0755))
  2649  	tg.setenv("GOPATH", tg.path("."))
  2650  	tg.setenv("PKG_CONFIG", tg.path("pkg-config.sh"))
  2651  	tg.run("build", "x")
  2652  	out, err := os.ReadFile(tg.path("pkg-config.out"))
  2653  	tg.must(err)
  2654  	out = bytes.TrimSpace(out)
  2655  	want := "--cflags --static --static -- a a\n--libs --static --static -- a a"
  2656  	if !bytes.Equal(out, []byte(want)) {
  2657  		t.Errorf("got %q want %q", out, want)
  2658  	}
  2659  }
  2660  
  2661  func TestCgoCache(t *testing.T) {
  2662  	testenv.MustHaveCGO(t)
  2663  	tooSlow(t, "builds a package with cgo dependencies")
  2664  
  2665  	tg := testgo(t)
  2666  	defer tg.cleanup()
  2667  	tg.parallel()
  2668  	tg.tempFile("src/x/a.go", `package main
  2669  		// #ifndef VAL
  2670  		// #define VAL 0
  2671  		// #endif
  2672  		// int val = VAL;
  2673  		import "C"
  2674  		import "fmt"
  2675  		func main() { fmt.Println(C.val) }
  2676  	`)
  2677  	tg.setenv("GOPATH", tg.path("."))
  2678  	exe := tg.path("x.exe")
  2679  	tg.run("build", "-o", exe, "x")
  2680  	tg.setenv("CGO_LDFLAGS", "-lnosuchlibraryexists")
  2681  	tg.runFail("build", "-o", exe, "x")
  2682  	tg.grepStderr(`nosuchlibraryexists`, "did not run linker with changed CGO_LDFLAGS")
  2683  }
  2684  
  2685  // Issue 23982
  2686  func TestFilepathUnderCwdFormat(t *testing.T) {
  2687  	tg := testgo(t)
  2688  	defer tg.cleanup()
  2689  	tg.parallel()
  2690  	tg.run("test", "-x", "-cover", "log")
  2691  	tg.grepStderrNot(`\.log\.cover\.go`, "-x output should contain correctly formatted filepath under cwd")
  2692  }
  2693  
  2694  // Issue 24396.
  2695  func TestDontReportRemoveOfEmptyDir(t *testing.T) {
  2696  	tg := testgo(t)
  2697  	defer tg.cleanup()
  2698  	tg.parallel()
  2699  	tg.tempFile("src/a/a.go", `package a`)
  2700  	tg.setenv("GOPATH", tg.path("."))
  2701  	tg.run("install", "-x", "a")
  2702  	tg.run("install", "-x", "a")
  2703  	// The second install should have printed only a WORK= line,
  2704  	// nothing else.
  2705  	if bytes.Count(tg.stdout.Bytes(), []byte{'\n'})+bytes.Count(tg.stderr.Bytes(), []byte{'\n'}) > 1 {
  2706  		t.Error("unnecessary output when installing installed package")
  2707  	}
  2708  }
  2709  
  2710  // Issue 24704.
  2711  func TestLinkerTmpDirIsDeleted(t *testing.T) {
  2712  	skipIfGccgo(t, "gccgo does not use cmd/link")
  2713  	testenv.MustHaveCGO(t)
  2714  	tooSlow(t, "builds a package with cgo dependencies")
  2715  
  2716  	tg := testgo(t)
  2717  	defer tg.cleanup()
  2718  	tg.parallel()
  2719  	tg.tempFile("a.go", `package main; import "C"; func main() {}`)
  2720  	tg.run("build", "-ldflags", "-v", "-o", os.DevNull, tg.path("a.go"))
  2721  	// Find line that has "host link:" in linker output.
  2722  	stderr := tg.getStderr()
  2723  	var hostLinkLine string
  2724  	for _, line := range strings.Split(stderr, "\n") {
  2725  		if !strings.Contains(line, "host link:") {
  2726  			continue
  2727  		}
  2728  		hostLinkLine = line
  2729  		break
  2730  	}
  2731  	if hostLinkLine == "" {
  2732  		t.Fatal(`fail to find with "host link:" string in linker output`)
  2733  	}
  2734  	// Find parameter, like "/tmp/go-link-408556474/go.o" inside of
  2735  	// "host link:" line, and extract temp directory /tmp/go-link-408556474
  2736  	// out of it.
  2737  	tmpdir := hostLinkLine
  2738  	i := strings.Index(tmpdir, `go.o"`)
  2739  	if i == -1 {
  2740  		t.Fatalf(`fail to find "go.o" in "host link:" line %q`, hostLinkLine)
  2741  	}
  2742  	tmpdir = tmpdir[:i-1]
  2743  	i = strings.LastIndex(tmpdir, `"`)
  2744  	if i == -1 {
  2745  		t.Fatalf(`fail to find " in "host link:" line %q`, hostLinkLine)
  2746  	}
  2747  	tmpdir = tmpdir[i+1:]
  2748  	// Verify that temp directory has been removed.
  2749  	_, err := os.Stat(tmpdir)
  2750  	if err == nil {
  2751  		t.Fatalf("temp directory %q has not been removed", tmpdir)
  2752  	}
  2753  	if !os.IsNotExist(err) {
  2754  		t.Fatalf("Stat(%q) returns unexpected error: %v", tmpdir, err)
  2755  	}
  2756  }
  2757  
  2758  // Issue 25093.
  2759  func TestCoverpkgTestOnly(t *testing.T) {
  2760  	skipIfGccgo(t, "gccgo has no cover tool")
  2761  	tooSlow(t, "links and runs a test binary with coverage enabled")
  2762  
  2763  	tg := testgo(t)
  2764  	defer tg.cleanup()
  2765  	tg.parallel()
  2766  	tg.tempFile("src/a/a.go", `package a
  2767  		func F(i int) int {
  2768  			return i*i
  2769  		}`)
  2770  	tg.tempFile("src/atest/a_test.go", `
  2771  		package a_test
  2772  		import ( "a"; "testing" )
  2773  		func TestF(t *testing.T) { a.F(2) }
  2774  	`)
  2775  	tg.setenv("GOPATH", tg.path("."))
  2776  	tg.run("test", "-coverpkg=a", "atest")
  2777  	tg.grepStderrNot("no packages being tested depend on matches", "bad match message")
  2778  	tg.grepStdout("coverage: 100", "no coverage")
  2779  }
  2780  
  2781  // Regression test for golang.org/issue/34499: version command should not crash
  2782  // when executed in a deleted directory on Linux.
  2783  func TestExecInDeletedDir(t *testing.T) {
  2784  	switch runtime.GOOS {
  2785  	case "windows", "plan9",
  2786  		"aix",                // Fails with "device busy".
  2787  		"solaris", "illumos": // Fails with "invalid argument".
  2788  		t.Skipf("%v does not support removing the current working directory", runtime.GOOS)
  2789  	}
  2790  	tg := testgo(t)
  2791  	defer tg.cleanup()
  2792  
  2793  	wd, err := os.Getwd()
  2794  	tg.check(err)
  2795  	tg.makeTempdir()
  2796  	tg.check(os.Chdir(tg.tempdir))
  2797  	defer func() { tg.check(os.Chdir(wd)) }()
  2798  
  2799  	tg.check(os.Remove(tg.tempdir))
  2800  
  2801  	// `go version` should not fail
  2802  	tg.run("version")
  2803  }
  2804  

View as plain text