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.
32 "cmd/go/internal/cache"
34 "cmd/go/internal/robustio"
35 "cmd/go/internal/search"
37 "cmd/go/internal/vcweb/vcstest"
39 "cmd/go/internal/work"
46 // GOVCS defaults to public:git|hg,private:all,
47 // which breaks many tests here - they can't use non-git, non-hg VCS at all!
48 // Change to fully permissive.
49 // The tests of the GOVCS setting itself are in ../../testdata/script/govcs.txt.
50 os.Setenv("GOVCS", "*:all")
54 canRace = false // whether we can run the race detector
55 canCgo = false // whether we can use cgo
56 canMSan = false // whether we can run the memory sanitizer
57 canASan = false // whether we can run the address sanitizer
61 goHostOS, goHostArch string
62 cgoEnabled string // raw value from 'go env CGO_ENABLED'
65 var exeSuffix string = func() string {
66 if runtime.GOOS == "windows" {
72 func tooSlow(t *testing.T) {
74 // In -short mode; skip test, except run it on the {darwin,linux,windows}/amd64 builders.
75 if testenv.Builder() != "" && runtime.GOARCH == "amd64" && (runtime.GOOS == "linux" || runtime.GOOS == "darwin" || runtime.GOOS == "windows") {
79 t.Skip("skipping test in -short mode")
83 // testGOROOT is the GOROOT to use when running testgo, a cmd/go binary
84 // build from this process's current GOROOT, but run from a different
88 // testGOROOT_FINAL is the GOROOT_FINAL with which the test binary is assumed to
90 var testGOROOT_FINAL = os.Getenv("GOROOT_FINAL")
92 var testGOCACHE string
98 // The TestMain function creates a go command for testing purposes and
99 // deletes it after the tests have been run.
100 func TestMain(m *testing.M) {
101 // When CMDGO_TEST_RUN_MAIN is set, we're reusing the test binary as cmd/go.
102 // Enable the special behavior needed in cmd/go/internal/work,
103 // run the main func exported via export_test.go, and exit.
104 // We set CMDGO_TEST_RUN_MAIN via os.Setenv and testScript.setup.
105 if os.Getenv("CMDGO_TEST_RUN_MAIN") != "" {
106 cfg.SetGOROOT(cfg.GOROOT, true)
108 if v := os.Getenv("TESTGO_VERSION"); v != "" {
109 work.RuntimeVersion = v
112 if testGOROOT := os.Getenv("TESTGO_GOROOT"); testGOROOT != "" {
113 // Disallow installs to the GOROOT from which testgo was built.
114 // Installs to other GOROOTs — such as one set explicitly within a test — are ok.
115 work.AllowInstall = func(a *work.Action) error {
120 rel := search.InDir(a.Target, testGOROOT)
126 if _, file, line, ok := runtime.Caller(1); ok {
127 if shortFile := search.InDir(file, filepath.Join(testGOROOT, "src")); shortFile != "" {
130 callerPos = fmt.Sprintf("%s:%d: ", file, line)
132 return fmt.Errorf("%stestgo must not write to GOROOT (installing to %s)", callerPos, filepath.Join("GOROOT", rel))
136 if vcsTestHost := os.Getenv("TESTGO_VCSTEST_HOST"); vcsTestHost != "" {
137 vcs.VCSTestRepoURL = "http://" + vcsTestHost
138 vcs.VCSTestHosts = vcstest.Hosts
139 vcsTestTLSHost := os.Getenv("TESTGO_VCSTEST_TLS_HOST")
140 vcsTestClient, err := vcstest.TLSClient(os.Getenv("TESTGO_VCSTEST_CERT"))
142 fmt.Fprintf(os.Stderr, "loading certificates from $TESTGO_VCSTEST_CERT: %v", err)
144 var interceptors []web.Interceptor
145 for _, host := range vcstest.Hosts {
146 interceptors = append(interceptors,
147 web.Interceptor{Scheme: "http", FromHost: host, ToHost: vcsTestHost},
148 web.Interceptor{Scheme: "https", FromHost: host, ToHost: vcsTestTLSHost, Client: vcsTestClient})
150 web.EnableTestHooks(interceptors)
156 os.Setenv("CMDGO_TEST_RUN_MAIN", "true")
158 // $GO_GCFLAGS a compiler debug flag known to cmd/dist, make.bash, etc.
159 // It is not a standard go command flag; use os.Getenv, not cfg.Getenv.
160 if os.Getenv("GO_GCFLAGS") != "" {
161 fmt.Fprintf(os.Stderr, "testing: warning: no tests to run\n") // magic string for cmd/go
162 fmt.Printf("cmd/go test is not compatible with $GO_GCFLAGS being set\n")
169 if *proxyAddr != "" {
174 // Run with a temporary TMPDIR to check that the tests don't
175 // leave anything behind.
176 topTmpdir, err := os.MkdirTemp("", "cmd-go-test-")
181 defer removeAll(topTmpdir)
183 fmt.Fprintf(os.Stderr, "TESTWORK: preserving top level tempdir %s\n", topTmpdir)
185 os.Setenv(tempEnvName(), topTmpdir)
187 dir, err := os.MkdirTemp(topTmpdir, "tmpdir")
193 defer removeAll(testTmpDir)
196 testGOCACHE = cache.DefaultDir()
197 if testenv.HasGoBuild() {
198 testBin = filepath.Join(testTmpDir, "testbin")
199 if err := os.Mkdir(testBin, 0777); err != nil {
202 testGo = filepath.Join(testBin, "go"+exeSuffix)
203 gotool, err := testenv.GoTool()
205 fmt.Fprintln(os.Stderr, "locating go tool: ", err)
209 goEnv := func(name string) string {
210 out, err := exec.Command(gotool, "env", name).CombinedOutput()
212 fmt.Fprintf(os.Stderr, "go env %s: %v\n%s", name, err, out)
215 return strings.TrimSpace(string(out))
217 testGOROOT = goEnv("GOROOT")
218 os.Setenv("TESTGO_GOROOT", testGOROOT)
219 // Ensure that GOROOT is set explicitly.
220 // Otherwise, if the toolchain was built with GOROOT_FINAL set but has not
221 // yet been moved to its final location, programs that invoke runtime.GOROOT
222 // may accidentally use the wrong path.
223 os.Setenv("GOROOT", testGOROOT)
225 // The whole GOROOT/pkg tree was installed using the GOHOSTOS/GOHOSTARCH
226 // toolchain (installed in GOROOT/pkg/tool/GOHOSTOS_GOHOSTARCH).
227 // The testgo.exe we are about to create will be built for GOOS/GOARCH,
228 // which means it will use the GOOS/GOARCH toolchain
229 // (installed in GOROOT/pkg/tool/GOOS_GOARCH).
230 // If these are not the same toolchain, then the entire standard library
231 // will look out of date (the compilers in those two different tool directories
232 // are built for different architectures and have different build IDs),
233 // which will cause many tests to do unnecessary rebuilds and some
234 // tests to attempt to overwrite the installed standard library.
235 // Bail out entirely in this case.
236 goHostOS = goEnv("GOHOSTOS")
237 os.Setenv("TESTGO_GOHOSTOS", goHostOS)
238 goHostArch = goEnv("GOHOSTARCH")
239 os.Setenv("TESTGO_GOHOSTARCH", goHostArch)
241 cgoEnabled = goEnv("CGO_ENABLED")
242 canCgo, err = strconv.ParseBool(cgoEnabled)
244 fmt.Fprintf(os.Stderr, "can't parse go env CGO_ENABLED output: %q\n", strings.TrimSpace(cgoEnabled))
248 // Duplicate the test executable into the path at testGo, for $PATH.
249 // If the OS supports symlinks, use them instead of copying bytes.
250 testExe, err := os.Executable()
254 if err := os.Symlink(testExe, testGo); err != nil {
255 // Otherwise, copy the bytes.
256 src, err := os.Open(testExe)
262 dst, err := os.OpenFile(testGo, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o777)
267 _, err = io.Copy(dst, src)
268 if closeErr := dst.Close(); err == nil {
276 out, err := exec.Command(gotool, "env", "GOCACHE").CombinedOutput()
278 fmt.Fprintf(os.Stderr, "could not find testing GOCACHE: %v\n%s", err, out)
281 testGOCACHE = strings.TrimSpace(string(out))
283 canMSan = canCgo && platform.MSanSupported(runtime.GOOS, runtime.GOARCH)
284 canASan = canCgo && platform.ASanSupported(runtime.GOOS, runtime.GOARCH)
285 canRace = canCgo && platform.RaceDetectorSupported(runtime.GOOS, runtime.GOARCH)
286 // The race detector doesn't work on Alpine Linux:
287 // golang.org/issue/14481
288 // gccgo does not support the race detector.
289 if isAlpineLinux() || runtime.Compiler == "gccgo" {
294 // Don't let these environment variables confuse the test.
295 os.Setenv("GOENV", "off")
296 os.Unsetenv("GOFLAGS")
298 os.Unsetenv("GOPATH")
299 os.Unsetenv("GIT_ALLOW_PROTOCOL")
300 os.Setenv("HOME", "/test-go-home-does-not-exist")
301 // On some systems the default C compiler is ccache.
302 // Setting HOME to a non-existent directory will break
303 // those systems. Disable ccache and use real compiler. Issue 17668.
304 os.Setenv("CCACHE_DISABLE", "1")
305 if cfg.Getenv("GOCACHE") == "" {
306 os.Setenv("GOCACHE", testGOCACHE) // because $HOME is gone
309 if testenv.Builder() != "" || os.Getenv("GIT_TRACE_CURL") == "1" {
310 // To help diagnose https://go.dev/issue/52545,
311 // enable tracing for Git HTTPS requests.
312 os.Setenv("GIT_TRACE_CURL", "1")
313 os.Setenv("GIT_TRACE_CURL_NO_DATA", "1")
314 os.Setenv("GIT_REDACT_COOKIES", "o,SSO,GSSO_Uberproxy")
319 removeAll(testTmpDir) // os.Exit won't run defer
323 // There shouldn't be anything left in topTmpdir.
324 dirf, err := os.Open(topTmpdir)
328 names, err := dirf.Readdirnames(0)
333 log.Fatalf("unexpected files left in tmpdir: %v", names)
342 func isAlpineLinux() bool {
343 if runtime.GOOS != "linux" {
346 fi, err := os.Lstat("/etc/alpine-release")
347 return err == nil && fi.Mode().IsRegular()
350 // The length of an mtime tick on this system. This is an estimate of
351 // how long we need to sleep to ensure that the mtime of two files is
353 // We used to try to be clever but that didn't always work (see golang.org/issue/12205).
354 var mtimeTick time.Duration = 1 * time.Second
356 // Manage a single run of the testgo binary.
357 type testgoData struct {
364 stdout, stderr bytes.Buffer
365 execDir string // dir for tg.run
368 // skipIfGccgo skips the test if using gccgo.
369 func skipIfGccgo(t *testing.T, msg string) {
370 if runtime.Compiler == "gccgo" {
371 t.Skipf("skipping test not supported on gccgo: %s", msg)
375 // testgo sets up for a test that runs testgo.
376 func testgo(t *testing.T) *testgoData {
378 testenv.MustHaveGoBuild(t)
379 testenv.SkipIfShortAndSlow(t)
381 return &testgoData{t: t}
384 // must gives a fatal error if err is not nil.
385 func (tg *testgoData) must(err error) {
392 // check gives a test non-fatal error if err is not nil.
393 func (tg *testgoData) check(err error) {
400 // parallel runs the test in parallel by calling t.Parallel.
401 func (tg *testgoData) parallel() {
404 tg.t.Fatal("internal testsuite error: call to parallel after run")
406 for _, e := range tg.env {
407 if strings.HasPrefix(e, "GOROOT=") || strings.HasPrefix(e, "GOPATH=") || strings.HasPrefix(e, "GOBIN=") {
408 val := e[strings.Index(e, "=")+1:]
409 if strings.HasPrefix(val, "testdata") || strings.HasPrefix(val, "./testdata") {
410 tg.t.Fatalf("internal testsuite error: call to parallel with testdata in environment (%s)", e)
418 // pwd returns the current directory.
419 func (tg *testgoData) pwd() string {
421 wd, err := os.Getwd()
423 tg.t.Fatalf("could not get working directory: %v", err)
428 // sleep sleeps for one tick, where a tick is a conservative estimate
429 // of how long it takes for a file modification to get a different
431 func (tg *testgoData) sleep() {
432 time.Sleep(mtimeTick)
435 // setenv sets an environment variable to use when running the test go
437 func (tg *testgoData) setenv(name, val string) {
439 if tg.inParallel && (name == "GOROOT" || name == "GOPATH" || name == "GOBIN") && (strings.HasPrefix(val, "testdata") || strings.HasPrefix(val, "./testdata")) {
440 tg.t.Fatalf("internal testsuite error: call to setenv with testdata (%s=%s) after parallel", name, val)
443 tg.env = append(tg.env, name+"="+val)
446 // unsetenv removes an environment variable.
447 func (tg *testgoData) unsetenv(name string) {
449 tg.env = append([]string(nil), os.Environ()...)
450 tg.env = append(tg.env, "GO111MODULE=off")
452 for i, v := range tg.env {
453 if strings.HasPrefix(v, name+"=") {
454 tg.env = append(tg.env[:i], tg.env[i+1:]...)
460 func (tg *testgoData) goTool() string {
464 // doRun runs the test go command, recording stdout and stderr and
465 // returning exit status.
466 func (tg *testgoData) doRun(args []string) error {
469 for _, arg := range args {
470 if strings.HasPrefix(arg, "testdata") || strings.HasPrefix(arg, "./testdata") {
471 tg.t.Fatal("internal testsuite error: parallel run using testdata")
477 for _, v := range tg.env {
478 if strings.HasPrefix(v, "GOROOT=") {
485 tg.setenv("GOROOT", testGOROOT)
488 tg.t.Logf("running testgo %v", args)
489 cmd := exec.Command(prog, args...)
493 cmd.Stdout = &tg.stdout
494 cmd.Stderr = &tg.stderr
497 if tg.stdout.Len() > 0 {
498 tg.t.Log("standard output:")
499 tg.t.Log(tg.stdout.String())
501 if tg.stderr.Len() > 0 {
502 tg.t.Log("standard error:")
503 tg.t.Log(tg.stderr.String())
509 // run runs the test go command, and expects it to succeed.
510 func (tg *testgoData) run(args ...string) {
512 if status := tg.doRun(args); status != nil {
514 tg.t.Logf("go %v failed unexpectedly in %s: %v", args, wd, status)
519 // runFail runs the test go command, and expects it to fail.
520 func (tg *testgoData) runFail(args ...string) {
522 if status := tg.doRun(args); status == nil {
523 tg.t.Fatal("testgo succeeded unexpectedly")
525 tg.t.Log("testgo failed as expected:", status)
529 // runGit runs a git command, and expects it to succeed.
530 func (tg *testgoData) runGit(dir string, args ...string) {
532 cmd := exec.Command("git", args...)
535 cmd.Stdout = &tg.stdout
536 cmd.Stderr = &tg.stderr
540 if tg.stdout.Len() > 0 {
541 tg.t.Log("git standard output:")
542 tg.t.Log(tg.stdout.String())
544 if tg.stderr.Len() > 0 {
545 tg.t.Log("git standard error:")
546 tg.t.Log(tg.stderr.String())
549 tg.t.Logf("git %v failed unexpectedly: %v", args, status)
554 // getStdout returns standard output of the testgo run as a string.
555 func (tg *testgoData) getStdout() string {
558 tg.t.Fatal("internal testsuite error: stdout called before run")
560 return tg.stdout.String()
563 // getStderr returns standard error of the testgo run as a string.
564 func (tg *testgoData) getStderr() string {
567 tg.t.Fatal("internal testsuite error: stdout called before run")
569 return tg.stderr.String()
572 // doGrepMatch looks for a regular expression in a buffer, and returns
573 // whether it is found. The regular expression is matched against
574 // each line separately, as with the grep command.
575 func (tg *testgoData) doGrepMatch(match string, b *bytes.Buffer) bool {
578 tg.t.Fatal("internal testsuite error: grep called before run")
580 re := regexp.MustCompile(match)
581 for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) {
589 // doGrep looks for a regular expression in a buffer and fails if it
590 // is not found. The name argument is the name of the output we are
591 // searching, "output" or "error". The msg argument is logged on
593 func (tg *testgoData) doGrep(match string, b *bytes.Buffer, name, msg string) {
595 if !tg.doGrepMatch(match, b) {
597 tg.t.Logf("pattern %v not found in standard %s", match, name)
602 // grepStdout looks for a regular expression in the test run's
603 // standard output and fails, logging msg, if it is not found.
604 func (tg *testgoData) grepStdout(match, msg string) {
606 tg.doGrep(match, &tg.stdout, "output", msg)
609 // grepStderr looks for a regular expression in the test run's
610 // standard error and fails, logging msg, if it is not found.
611 func (tg *testgoData) grepStderr(match, msg string) {
613 tg.doGrep(match, &tg.stderr, "error", msg)
616 // grepBoth looks for a regular expression in the test run's standard
617 // output or stand error and fails, logging msg, if it is not found.
618 func (tg *testgoData) grepBoth(match, msg string) {
620 if !tg.doGrepMatch(match, &tg.stdout) && !tg.doGrepMatch(match, &tg.stderr) {
622 tg.t.Logf("pattern %v not found in standard output or standard error", match)
627 // doGrepNot looks for a regular expression in a buffer and fails if
628 // it is found. The name and msg arguments are as for doGrep.
629 func (tg *testgoData) doGrepNot(match string, b *bytes.Buffer, name, msg string) {
631 if tg.doGrepMatch(match, b) {
633 tg.t.Logf("pattern %v found unexpectedly in standard %s", match, name)
638 // grepStdoutNot looks for a regular expression in the test run's
639 // standard output and fails, logging msg, if it is found.
640 func (tg *testgoData) grepStdoutNot(match, msg string) {
642 tg.doGrepNot(match, &tg.stdout, "output", msg)
645 // grepStderrNot looks for a regular expression in the test run's
646 // standard error and fails, logging msg, if it is found.
647 func (tg *testgoData) grepStderrNot(match, msg string) {
649 tg.doGrepNot(match, &tg.stderr, "error", msg)
652 // grepBothNot looks for a regular expression in the test run's
653 // standard output or standard error and fails, logging msg, if it is
655 func (tg *testgoData) grepBothNot(match, msg string) {
657 if tg.doGrepMatch(match, &tg.stdout) || tg.doGrepMatch(match, &tg.stderr) {
659 tg.t.Fatalf("pattern %v found unexpectedly in standard output or standard error", match)
663 // doGrepCount counts the number of times a regexp is seen in a buffer.
664 func (tg *testgoData) doGrepCount(match string, b *bytes.Buffer) int {
667 tg.t.Fatal("internal testsuite error: doGrepCount called before run")
669 re := regexp.MustCompile(match)
671 for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) {
679 // grepCountBoth returns the number of times a regexp is seen in both
680 // standard output and standard error.
681 func (tg *testgoData) grepCountBoth(match string) int {
683 return tg.doGrepCount(match, &tg.stdout) + tg.doGrepCount(match, &tg.stderr)
686 // creatingTemp records that the test plans to create a temporary file
687 // or directory. If the file or directory exists already, it will be
688 // removed. When the test completes, the file or directory will be
689 // removed if it exists.
690 func (tg *testgoData) creatingTemp(path string) {
692 if filepath.IsAbs(path) && !strings.HasPrefix(path, tg.tempdir) {
693 tg.t.Fatalf("internal testsuite error: creatingTemp(%q) with absolute path not in temporary directory", path)
695 tg.must(robustio.RemoveAll(path))
696 tg.temps = append(tg.temps, path)
699 // makeTempdir makes a temporary directory for a run of testgo. If
700 // the temporary directory was already created, this does nothing.
701 func (tg *testgoData) makeTempdir() {
703 if tg.tempdir == "" {
705 tg.tempdir, err = os.MkdirTemp("", "gotest")
710 // tempFile adds a temporary file for a run of testgo.
711 func (tg *testgoData) tempFile(path, contents string) {
714 tg.must(os.MkdirAll(filepath.Join(tg.tempdir, filepath.Dir(path)), 0755))
715 bytes := []byte(contents)
716 if strings.HasSuffix(path, ".go") {
717 formatted, err := format.Source(bytes)
722 tg.must(os.WriteFile(filepath.Join(tg.tempdir, path), bytes, 0644))
725 // tempDir adds a temporary directory for a run of testgo.
726 func (tg *testgoData) tempDir(path string) {
729 if err := os.MkdirAll(filepath.Join(tg.tempdir, path), 0755); err != nil && !os.IsExist(err) {
734 // path returns the absolute pathname to file with the temporary
736 func (tg *testgoData) path(name string) string {
738 if tg.tempdir == "" {
739 tg.t.Fatalf("internal testsuite error: path(%q) with no tempdir", name)
744 return filepath.Join(tg.tempdir, name)
747 // mustExist fails if path does not exist.
748 func (tg *testgoData) mustExist(path string) {
750 if _, err := os.Stat(path); err != nil {
751 if os.IsNotExist(err) {
752 tg.t.Fatalf("%s does not exist but should", path)
754 tg.t.Fatalf("%s stat failed: %v", path, err)
758 // mustNotExist fails if path exists.
759 func (tg *testgoData) mustNotExist(path string) {
761 if _, err := os.Stat(path); err == nil || !os.IsNotExist(err) {
762 tg.t.Fatalf("%s exists but should not (%v)", path, err)
766 // mustHaveContent succeeds if filePath is a path to a file,
767 // and that file is readable and not empty.
768 func (tg *testgoData) mustHaveContent(filePath string) {
769 tg.mustExist(filePath)
770 f, err := os.Stat(filePath)
775 tg.t.Fatalf("expected %s to have data, but is empty", filePath)
779 // wantExecutable fails with msg if path is not executable.
780 func (tg *testgoData) wantExecutable(path, msg string) {
782 if st, err := os.Stat(path); err != nil {
783 if !os.IsNotExist(err) {
788 if runtime.GOOS != "windows" && st.Mode()&0111 == 0 {
789 tg.t.Fatalf("binary %s exists but is not executable", path)
794 // isStale reports whether pkg is stale, and why
795 func (tg *testgoData) isStale(pkg string) (bool, string) {
797 tg.run("list", "-f", "{{.Stale}}:{{.StaleReason}}", pkg)
798 v := strings.TrimSpace(tg.getStdout())
799 f := strings.SplitN(v, ":", 2)
808 tg.t.Fatalf("unexpected output checking staleness of package %v: %v", pkg, v)
812 // wantStale fails with msg if pkg is not stale.
813 func (tg *testgoData) wantStale(pkg, reason, msg string) {
815 stale, why := tg.isStale(pkg)
819 // We always accept the reason as being "not installed but
820 // available in build cache", because when that is the case go
821 // list doesn't try to sort out the underlying reason why the
822 // package is not installed.
823 if reason == "" && why != "" || !strings.Contains(why, reason) && !strings.Contains(why, "not installed but available in build cache") {
824 tg.t.Errorf("wrong reason for Stale=true: %q, want %q", why, reason)
828 // wantNotStale fails with msg if pkg is stale.
829 func (tg *testgoData) wantNotStale(pkg, reason, msg string) {
831 stale, why := tg.isStale(pkg)
835 if reason == "" && why != "" || !strings.Contains(why, reason) {
836 tg.t.Errorf("wrong reason for Stale=false: %q, want %q", why, reason)
840 // If -testwork is specified, the test prints the name of the temp directory
841 // and does not remove it when done, so that a programmer can
842 // poke at the test file tree afterward.
843 var testWork = flag.Bool("testwork", false, "")
845 // cleanup cleans up a test that runs testgo.
846 func (tg *testgoData) cleanup() {
849 if tg.tempdir != "" {
850 tg.t.Logf("TESTWORK=%s\n", tg.path("."))
854 for _, path := range tg.temps {
855 tg.check(removeAll(path))
857 if tg.tempdir != "" {
858 tg.check(removeAll(tg.tempdir))
862 func removeAll(dir string) error {
863 // module cache has 0444 directories;
864 // make them writable in order to remove content.
865 filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error {
866 // chmod not only directories, but also things that we couldn't even stat
867 // due to permission errors: they may also be unreadable directories.
868 if err != nil || info.IsDir() {
873 return robustio.RemoveAll(dir)
876 // failSSH puts an ssh executable in the PATH that always fails.
877 // This is to stub out uses of ssh by go get.
878 func (tg *testgoData) failSSH() {
880 wd, err := os.Getwd()
884 fail := filepath.Join(wd, "testdata/failssh")
885 tg.setenv("PATH", fmt.Sprintf("%v%c%v", fail, filepath.ListSeparator, os.Getenv("PATH")))
888 func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
890 t.Skip("skipping lengthy test in short mode")
897 // Copy the runtime packages into a temporary GOROOT
898 // so that we can change files.
899 for _, copydir := range []string{
902 "src/internal/bytealg",
903 "src/internal/coverage/rtcov",
905 "src/internal/goarch",
906 "src/internal/goexperiment",
908 "src/internal/coverage/rtcov",
911 filepath.Join("pkg", runtime.GOOS+"_"+runtime.GOARCH),
912 filepath.Join("pkg/tool", goHostOS+"_"+goHostArch),
915 srcdir := filepath.Join(testGOROOT, copydir)
916 tg.tempDir(filepath.Join("goroot", copydir))
917 err := filepath.WalkDir(srcdir,
918 func(path string, info fs.DirEntry, err error) error {
925 srcrel, err := filepath.Rel(srcdir, path)
929 dest := filepath.Join("goroot", copydir, srcrel)
930 data, err := os.ReadFile(path)
934 tg.tempFile(dest, string(data))
935 if strings.Contains(copydir, filepath.Join("pkg", "tool")) {
936 os.Chmod(tg.path(dest), 0777)
944 tg.setenv("GOROOT", tg.path("goroot"))
946 addVar := func(name string, idx int) (restore func()) {
947 data, err := os.ReadFile(name)
952 data = append(data, fmt.Sprintf("var DummyUnusedVar%d bool\n", idx)...)
953 if err := os.WriteFile(name, append(data, '\n'), 0666); err != nil {
958 if err := os.WriteFile(name, old, 0666); err != nil {
964 // Every main package depends on the "runtime".
965 tg.tempFile("d1/src/p1/p1.go", `package main; func main(){}`)
966 tg.setenv("GOPATH", tg.path("d1"))
967 // Pass -i flag to rebuild everything outdated.
968 tg.run("install", "p1")
969 tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, before any changes")
971 // Changing mtime of runtime/internal/sys/sys.go
972 // should have no effect: only the content matters.
973 // In fact this should be true even outside a release branch.
974 sys := tg.path("goroot/src/runtime/internal/sys/sys.go")
976 restore := addVar(sys, 0)
978 tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after updating mtime of runtime/internal/sys/sys.go")
980 // But changing content of any file should have an effect.
981 // Previously zversion.go was the only one that mattered;
982 // now they all matter, so keep using sys.go.
983 restore = addVar(sys, 1)
985 tg.wantStale("p1", "stale dependency: runtime/internal", "./testgo list claims p1 is NOT stale, incorrectly, after changing sys.go")
987 tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after changing back to old release")
989 tg.wantStale("p1", "stale dependency: runtime", "./testgo list claims p1 is NOT stale, incorrectly, after changing sys.go again")
990 tg.run("install", "p1")
991 tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with new release")
993 // Restore to "old" release.
995 tg.wantStale("p1", "stale dependency: runtime/internal", "./testgo list claims p1 is NOT stale, incorrectly, after restoring sys.go")
996 tg.run("install", "p1")
997 tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with old release")
1000 // cmd/go: custom import path checking should not apply to Go packages without import comment.
1001 func TestIssue10952(t *testing.T) {
1002 testenv.MustHaveExternalNetwork(t)
1003 testenv.MustHaveExecPath(t, "git")
1009 tg.setenv("GOPATH", tg.path("."))
1010 const importPath = "github.com/zombiezen/go-get-issue-10952"
1011 tg.run("get", "-d", "-u", importPath)
1012 repoDir := tg.path("src/" + importPath)
1013 tg.runGit(repoDir, "remote", "set-url", "origin", "https://"+importPath+".git")
1014 tg.run("get", "-d", "-u", importPath)
1017 // Test git clone URL that uses SCP-like syntax and custom import path checking.
1018 func TestIssue11457(t *testing.T) {
1019 testenv.MustHaveExternalNetwork(t)
1020 testenv.MustHaveExecPath(t, "git")
1026 tg.setenv("GOPATH", tg.path("."))
1027 const importPath = "rsc.io/go-get-issue-11457"
1028 tg.run("get", "-d", "-u", importPath)
1029 repoDir := tg.path("src/" + importPath)
1030 tg.runGit(repoDir, "remote", "set-url", "origin", "git@github.com:rsc/go-get-issue-11457")
1032 // At this time, custom import path checking compares remotes verbatim (rather than
1033 // just the host and path, skipping scheme and user), so we expect go get -u to fail.
1034 // However, the goal of this test is to verify that gitRemoteRepo correctly parsed
1035 // the SCP-like syntax, and we expect it to appear in the error message.
1036 tg.runFail("get", "-d", "-u", importPath)
1037 want := " is checked out from ssh://git@github.com/rsc/go-get-issue-11457"
1038 if !strings.HasSuffix(strings.TrimSpace(tg.getStderr()), want) {
1039 t.Error("expected clone URL to appear in stderr")
1043 func TestGetGitDefaultBranch(t *testing.T) {
1044 testenv.MustHaveExternalNetwork(t)
1045 testenv.MustHaveExecPath(t, "git")
1051 tg.setenv("GOPATH", tg.path("."))
1053 // This repo has two branches, master and another-branch.
1054 // The another-branch is the default that you get from 'git clone'.
1055 // The go get command variants should not override this.
1056 const importPath = "github.com/rsc/go-get-default-branch"
1058 tg.run("get", "-d", importPath)
1059 repoDir := tg.path("src/" + importPath)
1060 tg.runGit(repoDir, "branch", "--contains", "HEAD")
1061 tg.grepStdout(`\* another-branch`, "not on correct default branch")
1063 tg.run("get", "-d", "-u", importPath)
1064 tg.runGit(repoDir, "branch", "--contains", "HEAD")
1065 tg.grepStdout(`\* another-branch`, "not on correct default branch")
1068 func TestPackageMainTestCompilerFlags(t *testing.T) {
1073 tg.setenv("GOPATH", tg.path("."))
1074 tg.tempFile("src/p1/p1.go", "package main\n")
1075 tg.tempFile("src/p1/p1_test.go", "package main\nimport \"testing\"\nfunc Test(t *testing.T){}\n")
1076 tg.run("test", "-c", "-n", "p1")
1077 tg.grepBothNot(`([\\/]compile|gccgo).* (-p main|-fgo-pkgpath=main).*p1\.go`, "should not have run compile -p main p1.go")
1078 tg.grepStderr(`([\\/]compile|gccgo).* (-p p1|-fgo-pkgpath=p1).*p1\.go`, "should have run compile -p p1 p1.go")
1082 func TestGoTestWithPackageListedMultipleTimes(t *testing.T) {
1087 tg.run("test", "errors", "errors", "errors", "errors", "errors")
1088 if strings.Contains(strings.TrimSpace(tg.getStdout()), "\n") {
1089 t.Error("go test errors errors errors errors errors tested the same package multiple times")
1093 func TestGoListHasAConsistentOrder(t *testing.T) {
1098 tg.run("list", "std")
1099 first := tg.getStdout()
1100 tg.run("list", "std")
1101 if first != tg.getStdout() {
1102 t.Error("go list std ordering is inconsistent")
1106 func TestGoListStdDoesNotIncludeCommands(t *testing.T) {
1111 tg.run("list", "std")
1112 tg.grepStdoutNot("cmd/", "go list std shows commands")
1115 func TestGoListCmdOnlyShowsCommands(t *testing.T) {
1116 skipIfGccgo(t, "gccgo does not have GOROOT")
1121 tg.run("list", "cmd")
1122 out := strings.TrimSpace(tg.getStdout())
1123 for _, line := range strings.Split(out, "\n") {
1124 if !strings.Contains(line, "cmd/") {
1125 t.Error("go list cmd shows non-commands")
1131 func TestGoListDeps(t *testing.T) {
1135 tg.tempDir("src/p1/p2/p3/p4")
1136 tg.setenv("GOPATH", tg.path("."))
1137 tg.tempFile("src/p1/p.go", "package p1\nimport _ \"p1/p2\"\n")
1138 tg.tempFile("src/p1/p2/p.go", "package p2\nimport _ \"p1/p2/p3\"\n")
1139 tg.tempFile("src/p1/p2/p3/p.go", "package p3\nimport _ \"p1/p2/p3/p4\"\n")
1140 tg.tempFile("src/p1/p2/p3/p4/p.go", "package p4\n")
1141 tg.run("list", "-f", "{{.Deps}}", "p1")
1142 tg.grepStdout("p1/p2/p3/p4", "Deps(p1) does not mention p4")
1144 tg.run("list", "-deps", "p1")
1145 tg.grepStdout("p1/p2/p3/p4", "-deps p1 does not mention p4")
1147 if runtime.Compiler != "gccgo" {
1148 // Check the list is in dependency order.
1149 tg.run("list", "-deps", "math")
1150 want := "internal/cpu\nunsafe\nmath/bits\nmath\n"
1151 out := tg.stdout.String()
1152 if !strings.Contains(out, "internal/cpu") {
1153 // Some systems don't use internal/cpu.
1154 want = "unsafe\nmath/bits\nmath\n"
1156 if tg.stdout.String() != want {
1157 t.Fatalf("list -deps math: wrong order\nhave %q\nwant %q", tg.stdout.String(), want)
1162 func TestGoListTest(t *testing.T) {
1163 skipIfGccgo(t, "gccgo does not have standard packages")
1168 tg.setenv("GOCACHE", tg.tempdir)
1170 tg.run("list", "-test", "-deps", "sort")
1171 tg.grepStdout(`^sort.test$`, "missing test main")
1172 tg.grepStdout(`^sort$`, "missing real sort")
1173 tg.grepStdout(`^sort \[sort.test\]$`, "missing test copy of sort")
1174 tg.grepStdout(`^testing \[sort.test\]$`, "missing test copy of testing")
1175 tg.grepStdoutNot(`^testing$`, "unexpected real copy of testing")
1177 tg.run("list", "-test", "sort")
1178 tg.grepStdout(`^sort.test$`, "missing test main")
1179 tg.grepStdout(`^sort$`, "missing real sort")
1180 tg.grepStdout(`^sort \[sort.test\]$`, "unexpected test copy of sort")
1181 tg.grepStdoutNot(`^testing \[sort.test\]$`, "unexpected test copy of testing")
1182 tg.grepStdoutNot(`^testing$`, "unexpected real copy of testing")
1184 tg.run("list", "-test", "cmd/buildid", "cmd/doc")
1185 tg.grepStdout(`^cmd/buildid$`, "missing cmd/buildid")
1186 tg.grepStdout(`^cmd/doc$`, "missing cmd/doc")
1187 tg.grepStdout(`^cmd/doc\.test$`, "missing cmd/doc test")
1188 tg.grepStdoutNot(`^cmd/buildid\.test$`, "unexpected cmd/buildid test")
1189 tg.grepStdoutNot(`^testing`, "unexpected testing")
1191 tg.run("list", "-test", "runtime/cgo")
1192 tg.grepStdout(`^runtime/cgo$`, "missing runtime/cgo")
1194 tg.run("list", "-deps", "-f", "{{if .DepOnly}}{{.ImportPath}}{{end}}", "sort")
1195 tg.grepStdout(`^internal/reflectlite$`, "missing internal/reflectlite")
1196 tg.grepStdoutNot(`^sort`, "unexpected sort")
1199 func TestGoListCompiledCgo(t *testing.T) {
1205 tg.setenv("GOCACHE", tg.tempdir)
1207 tg.run("list", "-f", `{{join .CgoFiles "\n"}}`, "net")
1208 if tg.stdout.String() == "" {
1209 t.Skip("net does not use cgo")
1211 if strings.Contains(tg.stdout.String(), tg.tempdir) {
1212 t.Fatalf(".CgoFiles unexpectedly mentioned cache %s", tg.tempdir)
1214 tg.run("list", "-compiled", "-f", `{{.Dir}}{{"\n"}}{{join .CompiledGoFiles "\n"}}`, "net")
1215 if !strings.Contains(tg.stdout.String(), tg.tempdir) {
1216 t.Fatalf(".CompiledGoFiles with -compiled did not mention cache %s", tg.tempdir)
1219 for _, file := range strings.Split(tg.stdout.String(), "\n") {
1227 if !strings.Contains(file, "/") && !strings.Contains(file, `\`) {
1228 file = filepath.Join(dir, file)
1230 if _, err := os.Stat(file); err != nil {
1231 t.Fatalf("cannot find .CompiledGoFiles result %s: %v", file, err)
1236 func TestGoListExport(t *testing.T) {
1237 skipIfGccgo(t, "gccgo does not have standard packages")
1242 tg.setenv("GOCACHE", tg.tempdir)
1244 tg.run("list", "-f", "{{.Export}}", "strings")
1245 if tg.stdout.String() != "" {
1246 t.Fatalf(".Export without -export unexpectedly set")
1248 tg.run("list", "-export", "-f", "{{.Export}}", "strings")
1249 file := strings.TrimSpace(tg.stdout.String())
1251 t.Fatalf(".Export with -export was empty")
1253 if _, err := os.Stat(file); err != nil {
1254 t.Fatalf("cannot find .Export result %s: %v", file, err)
1257 tg.run("list", "-export", "-f", "{{.BuildID}}", "strings")
1258 buildID := strings.TrimSpace(tg.stdout.String())
1260 t.Fatalf(".BuildID with -export was empty")
1263 tg.run("tool", "buildid", file)
1264 toolBuildID := strings.TrimSpace(tg.stdout.String())
1265 if buildID != toolBuildID {
1266 t.Fatalf(".BuildID with -export %q disagrees with 'go tool buildid' %q", buildID, toolBuildID)
1270 // Issue 4096. Validate the output of unsuccessful go install foo/quxx.
1271 func TestUnsuccessfulGoInstallShouldMentionMissingPackage(t *testing.T) {
1275 tg.runFail("install", "foo/quxx")
1276 if tg.grepCountBoth(`cannot find package "foo/quxx" in any of`) != 1 {
1277 t.Error(`go install foo/quxx expected error: .*cannot find package "foo/quxx" in any of`)
1281 func TestGOROOTSearchFailureReporting(t *testing.T) {
1285 tg.runFail("install", "foo/quxx")
1286 if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("foo", "quxx"))+` \(from \$GOROOT\)$`) != 1 {
1287 t.Error(`go install foo/quxx expected error: .*foo/quxx (from $GOROOT)`)
1291 func TestMultipleGOPATHEntriesReportedSeparately(t *testing.T) {
1295 sep := string(filepath.ListSeparator)
1296 tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
1297 tg.runFail("install", "foo/quxx")
1298 if tg.grepCountBoth(`testdata[/\\].[/\\]src[/\\]foo[/\\]quxx`) != 2 {
1299 t.Error(`go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)\n.*testdata/b/src/foo/quxx`)
1303 // Test (from $GOPATH) annotation is reported for the first GOPATH entry,
1304 func TestMentionGOPATHInFirstGOPATHEntry(t *testing.T) {
1308 sep := string(filepath.ListSeparator)
1309 tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
1310 tg.runFail("install", "foo/quxx")
1311 if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("testdata", "a", "src", "foo", "quxx"))+` \(from \$GOPATH\)$`) != 1 {
1312 t.Error(`go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)`)
1316 // but not on the second.
1317 func TestMentionGOPATHNotOnSecondEntry(t *testing.T) {
1321 sep := string(filepath.ListSeparator)
1322 tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
1323 tg.runFail("install", "foo/quxx")
1324 if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("testdata", "b", "src", "foo", "quxx"))+`$`) != 1 {
1325 t.Error(`go install foo/quxx expected error: .*testdata/b/src/foo/quxx`)
1329 func homeEnvName() string {
1330 switch runtime.GOOS {
1332 return "USERPROFILE"
1340 func tempEnvName() string {
1341 switch runtime.GOOS {
1345 return "TMPDIR" // actually plan 9 doesn't have one at all but this is fine
1351 func pathEnvName() string {
1352 switch runtime.GOOS {
1360 func TestDefaultGOPATH(t *testing.T) {
1364 tg.tempDir("home/go")
1365 tg.setenv(homeEnvName(), tg.path("home"))
1367 tg.run("env", "GOPATH")
1368 tg.grepStdout(regexp.QuoteMeta(tg.path("home/go")), "want GOPATH=$HOME/go")
1370 tg.setenv("GOROOT", tg.path("home/go"))
1371 tg.run("env", "GOPATH")
1372 tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go")
1374 tg.setenv("GOROOT", tg.path("home/go")+"/")
1375 tg.run("env", "GOPATH")
1376 tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go/")
1379 func TestDefaultGOPATHGet(t *testing.T) {
1380 testenv.MustHaveExternalNetwork(t)
1381 testenv.MustHaveExecPath(t, "git")
1386 tg.setenv("GOPATH", "")
1388 tg.setenv(homeEnvName(), tg.path("home"))
1390 // warn for creating directory
1391 tg.run("get", "-v", "github.com/golang/example/hello")
1392 tg.grepStderr("created GOPATH="+regexp.QuoteMeta(tg.path("home/go"))+"; see 'go help gopath'", "did not create GOPATH")
1394 // no warning if directory already exists
1395 tg.must(robustio.RemoveAll(tg.path("home/go")))
1396 tg.tempDir("home/go")
1397 tg.run("get", "github.com/golang/example/hello")
1398 tg.grepStderrNot(".", "expected no output on standard error")
1400 // error if $HOME/go is a file
1401 tg.must(robustio.RemoveAll(tg.path("home/go")))
1402 tg.tempFile("home/go", "")
1403 tg.runFail("get", "github.com/golang/example/hello")
1404 tg.grepStderr(`mkdir .*[/\\]go: .*(not a directory|cannot find the path)`, "expected error because $HOME/go is a file")
1407 func TestDefaultGOPATHPrintedSearchList(t *testing.T) {
1411 tg.setenv("GOPATH", "")
1413 tg.setenv(homeEnvName(), tg.path("home"))
1415 tg.runFail("install", "github.com/golang/example/hello")
1416 tg.grepStderr(regexp.QuoteMeta(tg.path("home/go/src/github.com/golang/example/hello"))+`.*from \$GOPATH`, "expected default GOPATH")
1419 func TestLdflagsArgumentsWithSpacesIssue3941(t *testing.T) {
1420 skipIfGccgo(t, "gccgo does not support -ldflags -X")
1425 tg.tempFile("main.go", `package main
1430 tg.run("run", "-ldflags", `-X "main.extern=hello world"`, tg.path("main.go"))
1431 tg.grepStderr("^hello world", `ldflags -X "main.extern=hello world"' failed`)
1434 func TestLdFlagsLongArgumentsIssue42295(t *testing.T) {
1435 // Test the extremely long command line arguments that contain '\n' characters
1436 // get encoded and passed correctly.
1437 skipIfGccgo(t, "gccgo does not support -ldflags -X")
1442 tg.tempFile("main.go", `package main
1447 testStr := "test test test test test \n\\ "
1448 var buf strings.Builder
1449 for buf.Len() < sys.ExecArgLengthLimit+1 {
1450 buf.WriteString(testStr)
1452 tg.run("run", "-ldflags", fmt.Sprintf(`-X "main.extern=%s"`, buf.String()), tg.path("main.go"))
1453 if tg.stderr.String() != buf.String() {
1454 t.Errorf("strings differ")
1458 func TestGoTestDashCDashOControlsBinaryLocation(t *testing.T) {
1459 skipIfGccgo(t, "gccgo has no standard packages")
1465 tg.run("test", "-c", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
1466 tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -c -o myerrors.test did not create myerrors.test")
1469 func TestGoTestDashOWritesBinary(t *testing.T) {
1470 skipIfGccgo(t, "gccgo has no standard packages")
1476 tg.run("test", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
1477 tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -o myerrors.test did not create myerrors.test")
1481 func TestInstallWithTags(t *testing.T) {
1487 tg.tempFile("src/example/a/main.go", `package main
1489 tg.tempFile("src/example/b/main.go", `// +build mytag
1493 tg.setenv("GOPATH", tg.path("."))
1494 tg.run("install", "-tags", "mytag", "example/a", "example/b")
1495 tg.wantExecutable(tg.path("bin/a"+exeSuffix), "go install example/a example/b did not install binaries")
1496 tg.wantExecutable(tg.path("bin/b"+exeSuffix), "go install example/a example/b did not install binaries")
1497 tg.must(os.Remove(tg.path("bin/a" + exeSuffix)))
1498 tg.must(os.Remove(tg.path("bin/b" + exeSuffix)))
1499 tg.run("install", "-tags", "mytag", "example/...")
1500 tg.wantExecutable(tg.path("bin/a"+exeSuffix), "go install example/... did not install binaries")
1501 tg.wantExecutable(tg.path("bin/b"+exeSuffix), "go install example/... did not install binaries")
1502 tg.run("list", "-tags", "mytag", "example/b...")
1503 if strings.TrimSpace(tg.getStdout()) != "example/b" {
1504 t.Error("go list example/b did not find example/b")
1508 // Issue 17451, 17662.
1509 func TestSymlinkWarning(t *testing.T) {
1514 tg.setenv("GOPATH", tg.path("."))
1516 tg.tempDir("src/example/xx")
1518 tg.tempFile("yy/zz/zz.go", "package zz\n")
1519 if err := os.Symlink(tg.path("yy"), tg.path("src/example/xx/yy")); err != nil {
1520 t.Skipf("symlink failed: %v", err)
1522 tg.run("list", "example/xx/z...")
1523 tg.grepStdoutNot(".", "list should not have matched anything")
1524 tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages")
1525 tg.grepStderrNot("symlink", "list should not have reported symlink")
1527 tg.run("list", "example/xx/...")
1528 tg.grepStdoutNot(".", "list should not have matched anything")
1529 tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages")
1530 tg.grepStderr("ignoring symlink", "list should have reported symlink")
1533 func TestCgoShowsFullPathNames(t *testing.T) {
1535 t.Skip("skipping because cgo not enabled")
1541 tg.tempFile("src/x/y/dirname/foo.go", `
1545 tg.setenv("GOPATH", tg.path("."))
1546 tg.runFail("build", "x/y/dirname")
1547 tg.grepBoth("x/y/dirname", "error did not use full path")
1550 func TestCgoHandlesWlORIGIN(t *testing.T) {
1553 t.Skip("skipping because cgo not enabled")
1559 tg.tempFile("src/origin/origin.go", `package origin
1560 // #cgo !darwin,!windows LDFLAGS: -Wl,-rpath,$ORIGIN
1563 func f() { C.f() }`)
1564 tg.setenv("GOPATH", tg.path("."))
1565 tg.run("build", "origin")
1568 func TestCgoPkgConfig(t *testing.T) {
1571 t.Skip("skipping because cgo not enabled")
1577 tg.run("env", "PKG_CONFIG")
1578 pkgConfig := strings.TrimSpace(tg.getStdout())
1579 testenv.MustHaveExecPath(t, pkgConfig)
1580 if out, err := exec.Command(pkgConfig, "--atleast-pkgconfig-version", "0.24").CombinedOutput(); err != nil {
1581 t.Skipf("%s --atleast-pkgconfig-version 0.24: %v\n%s", pkgConfig, err, out)
1584 // OpenBSD's pkg-config is strict about whitespace and only
1585 // supports backslash-escaped whitespace. It does not support
1586 // quotes, which the normal freedesktop.org pkg-config does
1587 // support. See https://man.openbsd.org/pkg-config.1
1588 tg.tempFile("foo.pc", `
1590 Description: The foo library
1592 Cflags: -Dhello=10 -Dworld=+32 -DDEFINED_FROM_PKG_CONFIG=hello\ world
1594 tg.tempFile("foo.go", `package main
1597 #cgo pkg-config: foo
1599 return DEFINED_FROM_PKG_CONFIG;
1606 if C.value() != 42 {
1607 println("value() =", C.value(), "wanted 42")
1612 tg.setenv("PKG_CONFIG_PATH", tg.path("."))
1613 tg.run("run", tg.path("foo.go"))
1616 func TestListTemplateContextFunction(t *testing.T) {
1618 for _, tt := range []struct {
1622 {"GOARCH", runtime.GOARCH},
1623 {"GOOS", runtime.GOOS},
1624 {"GOROOT", testGOROOT},
1625 {"GOPATH", os.Getenv("GOPATH")},
1627 {"UseAllFiles", ""},
1630 {"ReleaseTags", ""},
1631 {"InstallSuffix", ""},
1634 t.Run(tt.v, func(t *testing.T) {
1638 tmpl := "{{context." + tt.v + "}}"
1639 tg.run("list", "-f", tmpl)
1643 if got := strings.TrimSpace(tg.getStdout()); got != tt.want {
1644 t.Errorf("go list -f %q: got %q; want %q", tmpl, got, tt.want)
1650 // Test that you cannot use a local import in a package
1651 // accessed by a non-local import (found in a GOPATH/GOROOT).
1652 // See golang.org/issue/17475.
1653 func TestImportLocal(t *testing.T) {
1660 tg.tempFile("src/dir/x/x.go", `package x
1663 tg.setenv("GOPATH", tg.path("."))
1664 tg.run("build", "dir/x")
1666 // Ordinary import should work.
1667 tg.tempFile("src/dir/p0/p.go", `package p0
1671 tg.run("build", "dir/p0")
1673 // Relative import should not.
1674 tg.tempFile("src/dir/p1/p.go", `package p1
1678 tg.runFail("build", "dir/p1")
1679 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1681 // ... even in a test.
1682 tg.tempFile("src/dir/p2/p.go", `package p2
1684 tg.tempFile("src/dir/p2/p_test.go", `package p2
1688 func TestFoo(t *testing.T) {}
1690 tg.run("build", "dir/p2")
1691 tg.runFail("test", "dir/p2")
1692 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1694 // ... even in an xtest.
1695 tg.tempFile("src/dir/p2/p_test.go", `package p2_test
1699 func TestFoo(t *testing.T) {}
1701 tg.run("build", "dir/p2")
1702 tg.runFail("test", "dir/p2")
1703 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1705 // Relative import starting with ./ should not work either.
1706 tg.tempFile("src/dir/d.go", `package dir
1710 tg.runFail("build", "dir")
1711 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1713 // ... even in a test.
1714 tg.tempFile("src/dir/d.go", `package dir
1716 tg.tempFile("src/dir/d_test.go", `package dir
1720 func TestFoo(t *testing.T) {}
1722 tg.run("build", "dir")
1723 tg.runFail("test", "dir")
1724 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1726 // ... even in an xtest.
1727 tg.tempFile("src/dir/d_test.go", `package dir_test
1731 func TestFoo(t *testing.T) {}
1733 tg.run("build", "dir")
1734 tg.runFail("test", "dir")
1735 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1737 // Relative import plain ".." should not work.
1738 tg.tempFile("src/dir/x/y/y.go", `package dir
1742 tg.runFail("build", "dir/x/y")
1743 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1745 // ... even in a test.
1746 tg.tempFile("src/dir/x/y/y.go", `package y
1748 tg.tempFile("src/dir/x/y/y_test.go", `package y
1752 func TestFoo(t *testing.T) {}
1754 tg.run("build", "dir/x/y")
1755 tg.runFail("test", "dir/x/y")
1756 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1758 // ... even in an x test.
1759 tg.tempFile("src/dir/x/y/y_test.go", `package y_test
1763 func TestFoo(t *testing.T) {}
1765 tg.run("build", "dir/x/y")
1766 tg.runFail("test", "dir/x/y")
1767 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1769 // Relative import "." should not work.
1770 tg.tempFile("src/dir/x/xx.go", `package x
1774 tg.runFail("build", "dir/x")
1775 tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
1777 // ... even in a test.
1778 tg.tempFile("src/dir/x/xx.go", `package x
1780 tg.tempFile("src/dir/x/xx_test.go", `package x
1784 func TestFoo(t *testing.T) {}
1786 tg.run("build", "dir/x")
1787 tg.runFail("test", "dir/x")
1788 tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
1790 // ... even in an xtest.
1791 tg.tempFile("src/dir/x/xx.go", `package x
1793 tg.tempFile("src/dir/x/xx_test.go", `package x_test
1797 func TestFoo(t *testing.T) {}
1799 tg.run("build", "dir/x")
1800 tg.runFail("test", "dir/x")
1801 tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
1804 func TestGoInstallPkgdir(t *testing.T) {
1805 skipIfGccgo(t, "gccgo has no standard packages")
1807 // Only the stdlib packages that use cgo have install
1808 // targets, (we're using net below) so cgo is required
1810 t.Skip("skipping because cgo not enabled")
1816 tg.setenv("GODEBUG", "installgoroot=all")
1820 tg.run("install", "-pkgdir", pkg, "net")
1821 tg.mustExist(filepath.Join(pkg, "net.a"))
1822 tg.mustNotExist(filepath.Join(pkg, "runtime/cgo.a"))
1826 func TestParallelTest(t *testing.T) {
1832 const testSrc = `package package_test
1836 func TestTest(t *testing.T) {
1838 tg.tempFile("src/p1/p1_test.go", strings.Replace(testSrc, "package_test", "p1_test", 1))
1839 tg.tempFile("src/p2/p2_test.go", strings.Replace(testSrc, "package_test", "p2_test", 1))
1840 tg.tempFile("src/p3/p3_test.go", strings.Replace(testSrc, "package_test", "p3_test", 1))
1841 tg.tempFile("src/p4/p4_test.go", strings.Replace(testSrc, "package_test", "p4_test", 1))
1842 tg.setenv("GOPATH", tg.path("."))
1843 tg.run("test", "-p=4", "p1", "p2", "p3", "p4")
1846 func TestBinaryOnlyPackages(t *testing.T) {
1853 tg.setenv("GOPATH", tg.path("."))
1855 tg.tempFile("src/p1/p1.go", `//go:binary-only-package
1859 tg.wantStale("p1", "binary-only packages are no longer supported", "p1 is binary-only, and this message should always be printed")
1860 tg.runFail("install", "p1")
1861 tg.grepStderr("binary-only packages are no longer supported", "did not report attempt to compile binary-only package")
1863 tg.tempFile("src/p1/p1.go", `
1866 func F(b bool) { fmt.Printf("hello from p1\n"); if b { F(false) } }
1868 tg.run("install", "p1")
1869 os.Remove(tg.path("src/p1/p1.go"))
1870 tg.mustNotExist(tg.path("src/p1/p1.go"))
1872 tg.tempFile("src/p2/p2.go", `//go:binary-only-packages-are-not-great
1876 func F() { p1.F(true) }
1878 tg.runFail("install", "p2")
1879 tg.grepStderr("no Go files", "did not complain about missing sources")
1881 tg.tempFile("src/p1/missing.go", `//go:binary-only-package
1887 tg.wantStale("p1", "binary-only package", "should NOT want to rebuild p1 (first)")
1888 tg.runFail("install", "p2")
1889 tg.grepStderr("p1: binary-only packages are no longer supported", "did not report error for binary-only p1")
1891 tg.run("list", "-deps", "-f", "{{.ImportPath}}: {{.BinaryOnly}}", "p2")
1892 tg.grepStdout("p1: true", "p1 not listed as BinaryOnly")
1893 tg.grepStdout("p2: false", "p2 listed as BinaryOnly")
1896 // Issue 16050 and 21884.
1897 func TestLinkSysoFiles(t *testing.T) {
1898 if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
1899 t.Skip("not linux/amd64")
1905 tg.tempDir("src/syso")
1906 tg.tempFile("src/syso/a.syso", ``)
1907 tg.tempFile("src/syso/b.go", `package syso`)
1908 tg.setenv("GOPATH", tg.path("."))
1910 // We should see the .syso file regardless of the setting of
1913 tg.setenv("CGO_ENABLED", "1")
1914 tg.run("list", "-f", "{{.SysoFiles}}", "syso")
1915 tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=1")
1917 tg.setenv("CGO_ENABLED", "0")
1918 tg.run("list", "-f", "{{.SysoFiles}}", "syso")
1919 tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=0")
1921 tg.setenv("CGO_ENABLED", "1")
1922 tg.run("list", "-msan", "-f", "{{.SysoFiles}}", "syso")
1923 tg.grepStdoutNot("a.syso", "unexpected syso file with -msan")
1927 func TestGenerateUsesBuildContext(t *testing.T) {
1928 if runtime.GOOS == "windows" {
1929 t.Skip("this test won't run under Windows")
1935 tg.tempDir("src/gen")
1936 tg.tempFile("src/gen/gen.go", "package gen\n//go:generate echo $GOOS $GOARCH\n")
1937 tg.setenv("GOPATH", tg.path("."))
1939 tg.setenv("GOOS", "linux")
1940 tg.setenv("GOARCH", "amd64")
1941 tg.run("generate", "gen")
1942 tg.grepStdout("linux amd64", "unexpected GOOS/GOARCH combination")
1944 tg.setenv("GOOS", "darwin")
1945 tg.setenv("GOARCH", "arm64")
1946 tg.run("generate", "gen")
1947 tg.grepStdout("darwin arm64", "unexpected GOOS/GOARCH combination")
1950 func TestGoEnv(t *testing.T) {
1954 tg.setenv("GOOS", "freebsd") // to avoid invalid pair errors
1955 tg.setenv("GOARCH", "arm")
1956 tg.run("env", "GOARCH")
1957 tg.grepStdout("^arm$", "GOARCH not honored")
1959 tg.run("env", "GCCGO")
1960 tg.grepStdout(".", "GCCGO unexpectedly empty")
1962 tg.run("env", "CGO_CFLAGS")
1963 tg.grepStdout(".", "default CGO_CFLAGS unexpectedly empty")
1965 tg.setenv("CGO_CFLAGS", "-foobar")
1966 tg.run("env", "CGO_CFLAGS")
1967 tg.grepStdout("^-foobar$", "CGO_CFLAGS not honored")
1969 tg.setenv("CC", "gcc -fmust -fgo -ffaster")
1971 tg.grepStdout("gcc", "CC not found")
1972 tg.run("env", "GOGCCFLAGS")
1973 tg.grepStdout("-ffaster", "CC arguments not found")
1975 tg.run("env", "GOVERSION")
1976 envVersion := strings.TrimSpace(tg.stdout.String())
1979 cmdVersion := strings.TrimSpace(tg.stdout.String())
1981 // If 'go version' is "go version <version> <goos>/<goarch>", then
1982 // 'go env GOVERSION' is just "<version>".
1983 if cmdVersion == envVersion || !strings.Contains(cmdVersion, envVersion) {
1984 t.Fatalf("'go env GOVERSION' %q should be a shorter substring of 'go version' %q", envVersion, cmdVersion)
1989 noMatchesPattern = `(?m)^ok.*\[no tests to run\]`
1990 okPattern = `(?m)^ok`
1994 func TestLdBindNow(t *testing.T) {
1998 tg.setenv("LD_BIND_NOW", "1")
2003 // This is really a cmd/asm issue but this is a convenient place to test it.
2004 func TestConcurrentAsm(t *testing.T) {
2005 skipIfGccgo(t, "gccgo does not use cmd/asm")
2009 asm := `DATA ·constants<>+0x0(SB)/8,$0
2010 GLOBL ·constants<>(SB),8,$8
2012 tg.tempFile("go/src/p/a.s", asm)
2013 tg.tempFile("go/src/p/b.s", asm)
2014 tg.tempFile("go/src/p/p.go", `package p`)
2015 tg.setenv("GOPATH", tg.path("go"))
2016 tg.run("build", "p")
2020 func TestFFLAGS(t *testing.T) {
2022 t.Skip("skipping because cgo not enabled")
2029 tg.tempFile("p/src/p/main.go", `package main
2030 // #cgo FFLAGS: -no-such-fortran-flag
2034 tg.tempFile("p/src/p/a.f", `! comment`)
2035 tg.setenv("GOPATH", tg.path("p"))
2037 // This should normally fail because we are passing an unknown flag,
2038 // but issue #19080 points to Fortran compilers that succeed anyhow.
2039 // To work either way we call doRun directly rather than run or runFail.
2040 tg.doRun([]string{"build", "-x", "p"})
2042 tg.grepStderr("no-such-fortran-flag", `missing expected "-no-such-fortran-flag"`)
2046 // This is really a cmd/link issue but this is a convenient place to test it.
2047 func TestDuplicateGlobalAsmSymbols(t *testing.T) {
2048 skipIfGccgo(t, "gccgo does not use cmd/asm")
2050 if runtime.GOARCH != "386" && runtime.GOARCH != "amd64" {
2051 t.Skipf("skipping test on %s", runtime.GOARCH)
2054 t.Skip("skipping because cgo not enabled")
2062 #include "textflag.h"
2064 DATA sym<>+0x0(SB)/8,$0
2065 GLOBL sym<>(SB),(NOPTR+RODATA),$8
2067 TEXT ·Data(SB),NOSPLIT,$0
2072 tg.tempFile("go/src/a/a.s", asm)
2073 tg.tempFile("go/src/a/a.go", `package a; func Data() uint8`)
2074 tg.tempFile("go/src/b/b.s", asm)
2075 tg.tempFile("go/src/b/b.go", `package b; func Data() uint8`)
2076 tg.tempFile("go/src/p/p.go", `
2082 _ = a.Data() + b.Data()
2085 tg.setenv("GOPATH", tg.path("go"))
2086 exe := tg.path("p.exe")
2087 tg.creatingTemp(exe)
2088 tg.run("build", "-o", exe, "p")
2091 func copyFile(src, dst string, perm fs.FileMode) error {
2092 sf, err := os.Open(src)
2098 df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
2103 _, err = io.Copy(df, sf)
2111 func TestNeedVersion(t *testing.T) {
2112 skipIfGccgo(t, "gccgo does not use cmd/compile")
2116 tg.tempFile("goversion.go", `package main; func main() {}`)
2117 path := tg.path("goversion.go")
2118 tg.setenv("TESTGO_VERSION", "go1.testgo")
2119 tg.runFail("run", path)
2120 tg.grepStderr("compile", "does not match go tool version")
2123 func TestBuildmodePIE(t *testing.T) {
2124 if testing.Short() && testenv.Builder() == "" {
2125 t.Skipf("skipping in -short mode on non-builder")
2128 platform := fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)
2130 case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/riscv64", "linux/s390x",
2131 "android/amd64", "android/arm", "android/arm64", "android/386",
2133 "windows/386", "windows/amd64", "windows/arm":
2134 case "darwin/amd64":
2136 t.Skipf("skipping test because buildmode=pie is not supported on %s", platform)
2138 // Skip on alpine until https://go.dev/issues/54354 resolved.
2139 if strings.HasSuffix(testenv.Builder(), "-alpine") {
2140 t.Skip("skipping PIE tests on alpine; see https://go.dev/issues/54354")
2142 t.Run("non-cgo", func(t *testing.T) {
2143 testBuildmodePIE(t, false, true)
2146 switch runtime.GOOS {
2147 case "darwin", "freebsd", "linux", "windows":
2148 t.Run("cgo", func(t *testing.T) {
2149 testBuildmodePIE(t, true, true)
2155 func TestWindowsDefaultBuildmodIsPIE(t *testing.T) {
2156 if testing.Short() && testenv.Builder() == "" {
2157 t.Skipf("skipping in -short mode on non-builder")
2160 if runtime.GOOS != "windows" {
2161 t.Skip("skipping windows only test")
2164 t.Run("non-cgo", func(t *testing.T) {
2165 testBuildmodePIE(t, false, false)
2168 t.Run("cgo", func(t *testing.T) {
2169 testBuildmodePIE(t, true, false)
2174 func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) {
2183 tg.tempFile("main.go", fmt.Sprintf(`package main;%s func main() { print("hello") }`, s))
2184 src := tg.path("main.go")
2185 obj := tg.path("main.exe")
2186 args := []string{"build"}
2187 if setBuildmodeToPIE {
2188 args = append(args, "-buildmode=pie")
2190 args = append(args, "-o", obj, src)
2193 switch runtime.GOOS {
2194 case "linux", "android", "freebsd":
2195 f, err := elf.Open(obj)
2200 if f.Type != elf.ET_DYN {
2201 t.Errorf("PIE type must be ET_DYN, but %s", f.Type)
2204 f, err := macho.Open(obj)
2209 if f.Flags&macho.FlagDyldLink == 0 {
2210 t.Error("PIE must have DyldLink flag, but not")
2212 if f.Flags&macho.FlagPIE == 0 {
2213 t.Error("PIE must have PIE flag, but not")
2216 f, err := pe.Open(obj)
2221 if f.Section(".reloc") == nil {
2222 t.Error(".reloc section is not present")
2224 if (f.FileHeader.Characteristics & pe.IMAGE_FILE_RELOCS_STRIPPED) != 0 {
2225 t.Error("IMAGE_FILE_RELOCS_STRIPPED flag is set")
2228 switch oh := f.OptionalHeader.(type) {
2229 case *pe.OptionalHeader32:
2230 dc = oh.DllCharacteristics
2231 case *pe.OptionalHeader64:
2232 dc = oh.DllCharacteristics
2233 if (dc & pe.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) == 0 {
2234 t.Error("IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA flag is not set")
2237 t.Fatalf("unexpected optional header type of %T", f.OptionalHeader)
2239 if (dc & pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 {
2240 t.Error("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag is not set")
2243 // Test that only one symbol is exported (#40795).
2244 // PIE binaries don´t require .edata section but unfortunately
2245 // binutils doesn´t generate a .reloc section unless there is
2246 // at least one symbol exported.
2247 // See https://sourceware.org/bugzilla/show_bug.cgi?id=19011
2248 section := f.Section(".edata")
2250 t.Skip(".edata section is not present")
2252 // TODO: deduplicate this struct from cmd/link/internal/ld/pe.go
2253 type IMAGE_EXPORT_DIRECTORY struct {
2257 NumberOfFunctions uint32
2258 NumberOfNames uint32
2261 var e IMAGE_EXPORT_DIRECTORY
2262 if err := binary.Read(section.Open(), binary.LittleEndian, &e); err != nil {
2263 t.Fatalf("binary.Read failed: %v", err)
2266 // Only _cgo_dummy_export should be exported
2267 if e.NumberOfFunctions != 1 {
2268 t.Fatalf("got %d exported functions; want 1", e.NumberOfFunctions)
2270 if e.NumberOfNames != 1 {
2271 t.Fatalf("got %d exported names; want 1", e.NumberOfNames)
2275 panic("unreachable")
2278 out, err := exec.Command(obj).CombinedOutput()
2283 if string(out) != "hello" {
2284 t.Errorf("got %q; want %q", out, "hello")
2288 func TestUpxCompression(t *testing.T) {
2289 if runtime.GOOS != "linux" ||
2290 (runtime.GOARCH != "amd64" && runtime.GOARCH != "386") {
2291 t.Skipf("skipping upx test on %s/%s", runtime.GOOS, runtime.GOARCH)
2294 testenv.MustHaveExecPath(t, "upx")
2295 out, err := exec.Command("upx", "--version").CombinedOutput()
2297 t.Fatalf("upx --version failed: %v", err)
2300 // upx --version prints `upx <version>` in the first line of output:
2303 re := regexp.MustCompile(`([[:digit:]]+)\.([[:digit:]]+)`)
2304 upxVersion := re.FindStringSubmatch(string(out))
2305 if len(upxVersion) != 3 {
2306 t.Fatalf("bad upx version string: %s", upxVersion)
2309 major, err1 := strconv.Atoi(upxVersion[1])
2310 minor, err2 := strconv.Atoi(upxVersion[2])
2311 if err1 != nil || err2 != nil {
2312 t.Fatalf("bad upx version string: %s", upxVersion[0])
2315 // Anything below 3.94 is known not to work with go binaries
2316 if (major < 3) || (major == 3 && minor < 94) {
2317 t.Skipf("skipping because upx version %v.%v is too old", major, minor)
2324 tg.tempFile("main.go", `package main; import "fmt"; func main() { fmt.Print("hello upx") }`)
2325 src := tg.path("main.go")
2326 obj := tg.path("main")
2327 tg.run("build", "-o", obj, src)
2329 out, err = exec.Command("upx", obj).CombinedOutput()
2331 t.Logf("executing upx\n%s\n", out)
2332 t.Fatalf("upx failed with %v", err)
2335 out, err = exec.Command(obj).CombinedOutput()
2338 t.Fatalf("running compressed go binary failed with error %s", err)
2340 if string(out) != "hello upx" {
2341 t.Fatalf("bad output from compressed go binary:\ngot %q; want %q", out, "hello upx")
2345 func TestCacheListStale(t *testing.T) {
2347 if godebug.Get("gocacheverify") == "1" {
2348 t.Skip("GODEBUG gocacheverify")
2354 tg.setenv("GOCACHE", tg.path("cache"))
2355 tg.tempFile("gopath/src/p/p.go", "package p; import _ \"q\"; func F(){}\n")
2356 tg.tempFile("gopath/src/q/q.go", "package q; func F(){}\n")
2357 tg.tempFile("gopath/src/m/m.go", "package main; import _ \"q\"; func main(){}\n")
2359 tg.setenv("GOPATH", tg.path("gopath"))
2360 tg.run("install", "p", "m")
2361 tg.run("list", "-f={{.ImportPath}} {{.Stale}}", "m", "q", "p")
2362 tg.grepStdout("^m false", "m should not be stale")
2363 tg.grepStdout("^q true", "q should be stale")
2364 tg.grepStdout("^p false", "p should not be stale")
2367 func TestCacheCoverage(t *testing.T) {
2370 if godebug.Get("gocacheverify") == "1" {
2371 t.Skip("GODEBUG gocacheverify")
2377 tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
2380 tg.setenv("GOCACHE", tg.path("c1"))
2381 tg.run("test", "-cover", "-short", "strings")
2382 tg.run("test", "-cover", "-short", "math", "strings")
2385 func TestIssue22588(t *testing.T) {
2386 // Don't get confused by stderr coming from tools.
2391 tg.wantNotStale("runtime", "", "must be non-stale to compare staleness under -toolexec")
2393 if _, err := os.Stat("/usr/bin/time"); err != nil {
2397 tg.run("list", "-f={{.Stale}}", "runtime")
2398 tg.run("list", "-toolexec=/usr/bin/time", "-f={{.Stale}}", "runtime")
2399 tg.grepStdout("false", "incorrectly reported runtime as stale")
2402 func TestIssue22531(t *testing.T) {
2404 if godebug.Get("gocacheverify") == "1" {
2405 t.Skip("GODEBUG gocacheverify")
2411 tg.setenv("GOPATH", tg.tempdir)
2412 tg.setenv("GOCACHE", tg.path("cache"))
2413 tg.tempFile("src/m/main.go", "package main /* c1 */; func main() {}\n")
2414 tg.run("install", "-x", "m")
2415 tg.run("list", "-f", "{{.Stale}}", "m")
2416 tg.grepStdout("false", "reported m as stale after install")
2417 tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix))
2419 // The link action ID did not include the full main build ID,
2420 // even though the full main build ID is written into the
2421 // eventual binary. That caused the following install to
2422 // be a no-op, thinking the gofmt binary was up-to-date,
2423 // even though .Stale could see it was not.
2424 tg.tempFile("src/m/main.go", "package main /* c2 */; func main() {}\n")
2425 tg.run("install", "-x", "m")
2426 tg.run("list", "-f", "{{.Stale}}", "m")
2427 tg.grepStdout("false", "reported m as stale after reinstall")
2428 tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix))
2431 func TestIssue22596(t *testing.T) {
2433 if godebug.Get("gocacheverify") == "1" {
2434 t.Skip("GODEBUG gocacheverify")
2440 tg.setenv("GOCACHE", tg.path("cache"))
2441 tg.tempFile("gopath1/src/p/p.go", "package p; func F(){}\n")
2442 tg.tempFile("gopath2/src/p/p.go", "package p; func F(){}\n")
2444 tg.setenv("GOPATH", tg.path("gopath1"))
2445 tg.run("list", "-f={{.Target}}", "p")
2446 target1 := strings.TrimSpace(tg.getStdout())
2447 tg.run("install", "p")
2448 tg.wantNotStale("p", "", "p stale after install")
2450 tg.setenv("GOPATH", tg.path("gopath2"))
2451 tg.run("list", "-f={{.Target}}", "p")
2452 target2 := strings.TrimSpace(tg.getStdout())
2453 tg.must(os.MkdirAll(filepath.Dir(target2), 0777))
2454 tg.must(copyFile(target1, target2, 0666))
2455 tg.wantStale("p", "build ID mismatch", "p not stale after copy from gopath1")
2456 tg.run("install", "p")
2457 tg.wantNotStale("p", "", "p stale after install2")
2460 func TestTestCache(t *testing.T) {
2463 if godebug.Get("gocacheverify") == "1" {
2464 t.Skip("GODEBUG gocacheverify")
2470 tg.setenv("GOPATH", tg.tempdir)
2471 tg.setenv("GOCACHE", tg.path("cache"))
2473 // The -p=1 in the commands below just makes the -x output easier to read.
2475 t.Log("\n\nINITIAL\n\n")
2477 tg.tempFile("src/p1/p1.go", "package p1\nvar X = 1\n")
2478 tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\nvar X = 1\n")
2479 tg.tempFile("src/t/t1/t1_test.go", "package t\nimport \"testing\"\nfunc Test1(*testing.T) {}\n")
2480 tg.tempFile("src/t/t2/t2_test.go", "package t\nimport _ \"p1\"\nimport \"testing\"\nfunc Test2(*testing.T) {}\n")
2481 tg.tempFile("src/t/t3/t3_test.go", "package t\nimport \"p1\"\nimport \"testing\"\nfunc Test3(t *testing.T) {t.Log(p1.X)}\n")
2482 tg.tempFile("src/t/t4/t4_test.go", "package t\nimport \"p2\"\nimport \"testing\"\nfunc Test4(t *testing.T) {t.Log(p2.X)}")
2483 tg.run("test", "-x", "-v", "-short", "t/...")
2485 t.Log("\n\nREPEAT\n\n")
2487 tg.run("test", "-x", "-v", "-short", "t/...")
2488 tg.grepStdout(`ok \tt/t1\t\(cached\)`, "did not cache t1")
2489 tg.grepStdout(`ok \tt/t2\t\(cached\)`, "did not cache t2")
2490 tg.grepStdout(`ok \tt/t3\t\(cached\)`, "did not cache t3")
2491 tg.grepStdout(`ok \tt/t4\t\(cached\)`, "did not cache t4")
2492 tg.grepStderrNot(`[\\/](compile|gccgo) `, "incorrectly ran compiler")
2493 tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker")
2494 tg.grepStderrNot(`p[0-9]\.test`, "incorrectly ran test")
2496 t.Log("\n\nCOMMENT\n\n")
2498 // Changing the program text without affecting the compiled package
2499 // should result in the package being rebuilt but nothing more.
2500 tg.tempFile("src/p1/p1.go", "package p1\nvar X = 01\n")
2501 tg.run("test", "-p=1", "-x", "-v", "-short", "t/...")
2502 tg.grepStdout(`ok \tt/t1\t\(cached\)`, "did not cache t1")
2503 tg.grepStdout(`ok \tt/t2\t\(cached\)`, "did not cache t2")
2504 tg.grepStdout(`ok \tt/t3\t\(cached\)`, "did not cache t3")
2505 tg.grepStdout(`ok \tt/t4\t\(cached\)`, "did not cache t4")
2506 tg.grepStderrNot(`([\\/](compile|gccgo) ).*t[0-9]_test\.go`, "incorrectly ran compiler")
2507 tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker")
2508 tg.grepStderrNot(`t[0-9]\.test.*test\.short`, "incorrectly ran test")
2510 t.Log("\n\nCHANGE\n\n")
2512 // Changing the actual package should have limited effects.
2513 tg.tempFile("src/p1/p1.go", "package p1\nvar X = 02\n")
2514 tg.run("test", "-p=1", "-x", "-v", "-short", "t/...")
2516 // p2 should have been rebuilt.
2517 tg.grepStderr(`([\\/]compile|gccgo).*p2.go`, "did not recompile p2")
2519 // t1 does not import anything, should not have been rebuilt.
2520 tg.grepStderrNot(`([\\/]compile|gccgo).*t1_test.go`, "incorrectly recompiled t1")
2521 tg.grepStderrNot(`([\\/]link|gccgo).*t1_test`, "incorrectly relinked t1_test")
2522 tg.grepStdout(`ok \tt/t1\t\(cached\)`, "did not cache t/t1")
2524 // t2 imports p1 and must be rebuilt and relinked,
2525 // but the change should not have any effect on the test binary,
2526 // so the test should not have been rerun.
2527 tg.grepStderr(`([\\/]compile|gccgo).*t2_test.go`, "did not recompile t2")
2528 tg.grepStderr(`([\\/]link|gccgo).*t2\.test`, "did not relink t2_test")
2529 // This check does not currently work with gccgo, as garbage
2530 // collection of unused variables is not turned on by default.
2531 if runtime.Compiler != "gccgo" {
2532 tg.grepStdout(`ok \tt/t2\t\(cached\)`, "did not cache t/t2")
2535 // t3 imports p1, and changing X changes t3's test binary.
2536 tg.grepStderr(`([\\/]compile|gccgo).*t3_test.go`, "did not recompile t3")
2537 tg.grepStderr(`([\\/]link|gccgo).*t3\.test`, "did not relink t3_test")
2538 tg.grepStderr(`t3\.test.*-test.short`, "did not rerun t3_test")
2539 tg.grepStdoutNot(`ok \tt/t3\t\(cached\)`, "reported cached t3_test result")
2541 // t4 imports p2, but p2 did not change, so t4 should be relinked, not recompiled,
2543 tg.grepStderrNot(`([\\/]compile|gccgo).*t4_test.go`, "incorrectly recompiled t4")
2544 tg.grepStderr(`([\\/]link|gccgo).*t4\.test`, "did not relink t4_test")
2545 // This check does not currently work with gccgo, as garbage
2546 // collection of unused variables is not turned on by default.
2547 if runtime.Compiler != "gccgo" {
2548 tg.grepStdout(`ok \tt/t4\t\(cached\)`, "did not cache t/t4")
2552 func TestTestSkipVetAfterFailedBuild(t *testing.T) {
2557 tg.tempFile("x_test.go", `package x
2563 tg.runFail("test", tg.path("x_test.go"))
2564 tg.grepStderrNot(`vet`, "vet should be skipped after the failed build")
2567 func TestTestVetRebuild(t *testing.T) {
2573 // golang.org/issue/23701.
2574 // b_test imports b with augmented method from export_test.go.
2575 // b_test also imports a, which imports b.
2576 // Must not accidentally see un-augmented b propagate through a to b_test.
2577 tg.tempFile("src/a/a.go", `package a
2580 func (*Type) M() b.T {return 0}
2582 tg.tempFile("src/b/b.go", `package b
2584 type I interface {M() T}
2586 tg.tempFile("src/b/export_test.go", `package b
2587 func (*T) Method() *T { return nil }
2589 tg.tempFile("src/b/b_test.go", `package b_test
2595 func TestBroken(t *testing.T) {
2602 tg.setenv("GOPATH", tg.path("."))
2607 func TestInstallDeps(t *testing.T) {
2613 tg.setenv("GOPATH", tg.tempdir)
2615 tg.tempFile("src/p1/p1.go", "package p1\nvar X = 1\n")
2616 tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\n")
2617 tg.tempFile("src/main1/main.go", "package main\nimport _ \"p2\"\nfunc main() {}\n")
2619 tg.run("list", "-f={{.Target}}", "p1")
2620 p1 := strings.TrimSpace(tg.getStdout())
2621 tg.run("list", "-f={{.Target}}", "p2")
2622 p2 := strings.TrimSpace(tg.getStdout())
2623 tg.run("list", "-f={{.Target}}", "main1")
2624 main1 := strings.TrimSpace(tg.getStdout())
2626 tg.run("install", "main1")
2632 tg.run("install", "p2")
2638 func TestImportPath(t *testing.T) {
2644 tg.tempFile("src/a/a.go", `
2658 tg.tempFile("src/a/a_test.go", `
2666 func TestV(t *testing.T) {
2672 tg.tempFile("src/a/p-1.0/p.go", `
2680 tg.setenv("GOPATH", tg.path("."))
2681 tg.run("build", "-o", tg.path("a.exe"), "a")
2685 func TestBadCommandLines(t *testing.T) {
2690 tg.tempFile("src/x/x.go", "package x\n")
2691 tg.setenv("GOPATH", tg.path("."))
2693 tg.run("build", "x")
2695 tg.tempFile("src/x/@y.go", "package x\n")
2696 tg.runFail("build", "x")
2697 tg.grepStderr("invalid input file name \"@y.go\"", "did not reject @y.go")
2698 tg.must(os.Remove(tg.path("src/x/@y.go")))
2700 tg.tempFile("src/x/-y.go", "package x\n")
2701 tg.runFail("build", "x")
2702 tg.grepStderr("invalid input file name \"-y.go\"", "did not reject -y.go")
2703 tg.must(os.Remove(tg.path("src/x/-y.go")))
2705 if runtime.Compiler == "gccgo" {
2706 tg.runFail("build", "-gccgoflags=all=@x", "x")
2708 tg.runFail("build", "-gcflags=all=@x", "x")
2710 tg.grepStderr("invalid command-line argument @x in command", "did not reject @x during exec")
2712 tg.tempFile("src/@x/x.go", "package x\n")
2713 tg.setenv("GOPATH", tg.path("."))
2714 tg.runFail("build", "@x")
2715 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")
2717 tg.tempFile("src/@x/y/y.go", "package y\n")
2718 tg.setenv("GOPATH", tg.path("."))
2719 tg.runFail("build", "@x/y")
2720 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")
2722 tg.tempFile("src/-x/x.go", "package x\n")
2723 tg.setenv("GOPATH", tg.path("."))
2724 tg.runFail("build", "--", "-x")
2725 tg.grepStderr("invalid import path \"-x\"", "did not reject -x import path")
2727 tg.tempFile("src/-x/y/y.go", "package y\n")
2728 tg.setenv("GOPATH", tg.path("."))
2729 tg.runFail("build", "--", "-x/y")
2730 tg.grepStderr("invalid import path \"-x/y\"", "did not reject -x/y import path")
2733 func TestTwoPkgConfigs(t *testing.T) {
2737 if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
2738 t.Skipf("no shell scripts on %s", runtime.GOOS)
2744 tg.tempFile("src/x/a.go", `package x
2745 // #cgo pkg-config: --static a
2748 tg.tempFile("src/x/b.go", `package x
2749 // #cgo pkg-config: --static a
2752 tg.tempFile("pkg-config.sh", `#!/bin/sh
2753 echo $* >>`+tg.path("pkg-config.out"))
2754 tg.must(os.Chmod(tg.path("pkg-config.sh"), 0755))
2755 tg.setenv("GOPATH", tg.path("."))
2756 tg.setenv("PKG_CONFIG", tg.path("pkg-config.sh"))
2757 tg.run("build", "x")
2758 out, err := os.ReadFile(tg.path("pkg-config.out"))
2760 out = bytes.TrimSpace(out)
2761 want := "--cflags --static --static -- a a\n--libs --static --static -- a a"
2762 if !bytes.Equal(out, []byte(want)) {
2763 t.Errorf("got %q want %q", out, want)
2767 func TestCgoCache(t *testing.T) {
2776 tg.tempFile("src/x/a.go", `package main
2783 func main() { fmt.Println(C.val) }
2785 tg.setenv("GOPATH", tg.path("."))
2786 exe := tg.path("x.exe")
2787 tg.run("build", "-o", exe, "x")
2788 tg.setenv("CGO_LDFLAGS", "-lnosuchlibraryexists")
2789 tg.runFail("build", "-o", exe, "x")
2790 tg.grepStderr(`nosuchlibraryexists`, "did not run linker with changed CGO_LDFLAGS")
2794 func TestFilepathUnderCwdFormat(t *testing.T) {
2798 tg.run("test", "-x", "-cover", "log")
2799 tg.grepStderrNot(`\.log\.cover\.go`, "-x output should contain correctly formatted filepath under cwd")
2803 func TestDontReportRemoveOfEmptyDir(t *testing.T) {
2807 tg.tempFile("src/a/a.go", `package a`)
2808 tg.setenv("GOPATH", tg.path("."))
2809 tg.run("install", "-x", "a")
2810 tg.run("install", "-x", "a")
2811 // The second install should have printed only a WORK= line,
2813 if bytes.Count(tg.stdout.Bytes(), []byte{'\n'})+bytes.Count(tg.stderr.Bytes(), []byte{'\n'}) > 1 {
2814 t.Error("unnecessary output when installing installed package")
2819 func TestLinkerTmpDirIsDeleted(t *testing.T) {
2820 skipIfGccgo(t, "gccgo does not use cmd/link")
2822 t.Skip("skipping because cgo not enabled")
2829 tg.tempFile("a.go", `package main; import "C"; func main() {}`)
2830 tg.run("build", "-ldflags", "-v", "-o", os.DevNull, tg.path("a.go"))
2831 // Find line that has "host link:" in linker output.
2832 stderr := tg.getStderr()
2833 var hostLinkLine string
2834 for _, line := range strings.Split(stderr, "\n") {
2835 if !strings.Contains(line, "host link:") {
2841 if hostLinkLine == "" {
2842 t.Fatal(`fail to find with "host link:" string in linker output`)
2844 // Find parameter, like "/tmp/go-link-408556474/go.o" inside of
2845 // "host link:" line, and extract temp directory /tmp/go-link-408556474
2847 tmpdir := hostLinkLine
2848 i := strings.Index(tmpdir, `go.o"`)
2850 t.Fatalf(`fail to find "go.o" in "host link:" line %q`, hostLinkLine)
2852 tmpdir = tmpdir[:i-1]
2853 i = strings.LastIndex(tmpdir, `"`)
2855 t.Fatalf(`fail to find " in "host link:" line %q`, hostLinkLine)
2857 tmpdir = tmpdir[i+1:]
2858 // Verify that temp directory has been removed.
2859 _, err := os.Stat(tmpdir)
2861 t.Fatalf("temp directory %q has not been removed", tmpdir)
2863 if !os.IsNotExist(err) {
2864 t.Fatalf("Stat(%q) returns unexpected error: %v", tmpdir, err)
2869 func TestCoverpkgTestOnly(t *testing.T) {
2870 skipIfGccgo(t, "gccgo has no cover tool")
2875 tg.tempFile("src/a/a.go", `package a
2879 tg.tempFile("src/atest/a_test.go", `
2881 import ( "a"; "testing" )
2882 func TestF(t *testing.T) { a.F(2) }
2884 tg.setenv("GOPATH", tg.path("."))
2885 tg.run("test", "-coverpkg=a", "atest")
2886 tg.grepStderrNot("no packages being tested depend on matches", "bad match message")
2887 tg.grepStdout("coverage: 100", "no coverage")
2890 // Regression test for golang.org/issue/34499: version command should not crash
2891 // when executed in a deleted directory on Linux.
2892 func TestExecInDeletedDir(t *testing.T) {
2893 switch runtime.GOOS {
2894 case "windows", "plan9",
2895 "aix", // Fails with "device busy".
2896 "solaris", "illumos": // Fails with "invalid argument".
2897 t.Skipf("%v does not support removing the current working directory", runtime.GOOS)
2902 wd, err := os.Getwd()
2905 tg.check(os.Chdir(tg.tempdir))
2906 defer func() { tg.check(os.Chdir(wd)) }()
2908 tg.check(os.Remove(tg.tempdir))
2910 // `go version` should not fail
2914 // A missing C compiler should not force the net package to be stale.
2916 func TestMissingCC(t *testing.T) {
2918 t.Skip("test is only meaningful on systems with cgo")
2920 cc := os.Getenv("CC")
2924 if filepath.IsAbs(cc) {
2925 t.Skipf(`"CC" (%s) is an absolute path`, cc)
2927 _, err := exec.LookPath(cc)
2929 t.Skipf(`"CC" (%s) not on PATH`, cc)
2934 netStale, _ := tg.isStale("net")
2936 t.Skip(`skipping test because "net" package is currently stale`)
2939 tg.setenv("PATH", "") // No C compiler on PATH.
2940 netStale, _ = tg.isStale("net")
2942 t.Error(`clearing "PATH" causes "net" to be stale`)