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"
39 // GOVCS defaults to public:git|hg,private:all,
40 // which breaks many tests here - they can't use non-git, non-hg VCS at all!
41 // Change to fully permissive.
42 // The tests of the GOVCS setting itself are in ../../testdata/script/govcs.txt.
43 os.Setenv("GOVCS", "*:all")
47 canRace = false // whether we can run the race detector
48 canCgo = false // whether we can use cgo
49 canMSan = false // whether we can run the memory sanitizer
50 canASan = false // whether we can run the address sanitizer
51 canFuzz = false // whether we can search for new fuzz failures
52 fuzzInstrumented = false // whether fuzzing uses instrumentation
55 var exeSuffix string = func() string {
56 if runtime.GOOS == "windows" {
62 func tooSlow(t *testing.T) {
64 // In -short mode; skip test, except run it on the {darwin,linux,windows}/amd64 builders.
65 if testenv.Builder() != "" && runtime.GOARCH == "amd64" && (runtime.GOOS == "linux" || runtime.GOOS == "darwin" || runtime.GOOS == "windows") {
69 t.Skip("skipping test in -short mode")
73 // testGOROOT is the GOROOT to use when running testgo, a cmd/go binary
74 // build from this process's current GOROOT, but run from a different
78 var testGOCACHE string
84 // The TestMain function creates a go command for testing purposes and
85 // deletes it after the tests have been run.
86 func TestMain(m *testing.M) {
87 // $GO_GCFLAGS a compiler debug flag known to cmd/dist, make.bash, etc.
88 // It is not a standard go command flag; use os.Getenv, not cfg.Getenv.
89 if os.Getenv("GO_GCFLAGS") != "" {
90 fmt.Fprintf(os.Stderr, "testing: warning: no tests to run\n") // magic string for cmd/go
91 fmt.Printf("cmd/go test is not compatible with $GO_GCFLAGS being set\n")
103 // Run with a temporary TMPDIR to check that the tests don't
104 // leave anything behind.
105 topTmpdir, err := os.MkdirTemp("", "cmd-go-test-")
110 defer removeAll(topTmpdir)
112 os.Setenv(tempEnvName(), topTmpdir)
114 dir, err := os.MkdirTemp(topTmpdir, "tmpdir")
120 defer removeAll(testTmpDir)
123 testGOCACHE = cache.DefaultDir()
124 if testenv.HasGoBuild() {
125 testBin = filepath.Join(testTmpDir, "testbin")
126 if err := os.Mkdir(testBin, 0777); err != nil {
129 testGo = filepath.Join(testBin, "go"+exeSuffix)
130 args := []string{"build", "-tags", "testgo", "-o", testGo}
132 args = append(args, "-race")
134 gotool, err := testenv.GoTool()
136 fmt.Fprintln(os.Stderr, err)
140 goEnv := func(name string) string {
141 out, err := exec.Command(gotool, "env", name).CombinedOutput()
143 fmt.Fprintf(os.Stderr, "go env %s: %v\n%s", name, err, out)
146 return strings.TrimSpace(string(out))
148 testGOROOT = goEnv("GOROOT")
149 os.Setenv("TESTGO_GOROOT", testGOROOT)
150 // Ensure that GOROOT is set explicitly.
151 // Otherwise, if the toolchain was built with GOROOT_FINAL set but has not
152 // yet been moved to its final location, programs that invoke runtime.GOROOT
153 // may accidentally use the wrong path.
154 os.Setenv("GOROOT", testGOROOT)
156 // The whole GOROOT/pkg tree was installed using the GOHOSTOS/GOHOSTARCH
157 // toolchain (installed in GOROOT/pkg/tool/GOHOSTOS_GOHOSTARCH).
158 // The testgo.exe we are about to create will be built for GOOS/GOARCH,
159 // which means it will use the GOOS/GOARCH toolchain
160 // (installed in GOROOT/pkg/tool/GOOS_GOARCH).
161 // If these are not the same toolchain, then the entire standard library
162 // will look out of date (the compilers in those two different tool directories
163 // are built for different architectures and have different build IDs),
164 // which will cause many tests to do unnecessary rebuilds and some
165 // tests to attempt to overwrite the installed standard library.
166 // Bail out entirely in this case.
167 hostGOOS := goEnv("GOHOSTOS")
168 hostGOARCH := goEnv("GOHOSTARCH")
169 if hostGOOS != runtime.GOOS || hostGOARCH != runtime.GOARCH {
170 fmt.Fprintf(os.Stderr, "testing: warning: no tests to run\n") // magic string for cmd/go
171 fmt.Printf("cmd/go test is not compatible with GOOS/GOARCH != GOHOSTOS/GOHOSTARCH (%s/%s != %s/%s)\n", runtime.GOOS, runtime.GOARCH, hostGOOS, hostGOARCH)
176 buildCmd := exec.Command(gotool, args...)
177 buildCmd.Env = append(os.Environ(), "GOFLAGS=-mod=vendor")
178 out, err := buildCmd.CombinedOutput()
180 fmt.Fprintf(os.Stderr, "building testgo failed: %v\n%s", err, out)
184 cmd := exec.Command(testGo, "env", "CGO_ENABLED")
185 cmd.Stderr = new(strings.Builder)
186 if out, err := cmd.Output(); err != nil {
187 fmt.Fprintf(os.Stderr, "running testgo failed: %v\n%s", err, cmd.Stderr)
190 canCgo, err = strconv.ParseBool(strings.TrimSpace(string(out)))
192 fmt.Fprintf(os.Stderr, "can't parse go env CGO_ENABLED output: %v\n", strings.TrimSpace(string(out)))
196 out, err = exec.Command(gotool, "env", "GOCACHE").CombinedOutput()
198 fmt.Fprintf(os.Stderr, "could not find testing GOCACHE: %v\n%s", err, out)
201 testGOCACHE = strings.TrimSpace(string(out))
203 canMSan = canCgo && sys.MSanSupported(runtime.GOOS, runtime.GOARCH)
204 canASan = canCgo && sys.ASanSupported(runtime.GOOS, runtime.GOARCH)
205 canRace = canCgo && sys.RaceDetectorSupported(runtime.GOOS, runtime.GOARCH)
206 // The race detector doesn't work on Alpine Linux:
207 // golang.org/issue/14481
208 // gccgo does not support the race detector.
209 if isAlpineLinux() || runtime.Compiler == "gccgo" {
212 canFuzz = sys.FuzzSupported(runtime.GOOS, runtime.GOARCH)
213 fuzzInstrumented = sys.FuzzInstrumented(runtime.GOOS, runtime.GOARCH)
215 // Don't let these environment variables confuse the test.
216 os.Setenv("GOENV", "off")
217 os.Unsetenv("GOFLAGS")
219 os.Unsetenv("GOPATH")
220 os.Unsetenv("GIT_ALLOW_PROTOCOL")
221 os.Setenv("HOME", "/test-go-home-does-not-exist")
222 // On some systems the default C compiler is ccache.
223 // Setting HOME to a non-existent directory will break
224 // those systems. Disable ccache and use real compiler. Issue 17668.
225 os.Setenv("CCACHE_DISABLE", "1")
226 if cfg.Getenv("GOCACHE") == "" {
227 os.Setenv("GOCACHE", testGOCACHE) // because $HOME is gone
232 removeAll(testTmpDir) // os.Exit won't run defer
236 // There shouldn't be anything left in topTmpdir.
237 dirf, err := os.Open(topTmpdir)
241 names, err := dirf.Readdirnames(0)
246 log.Fatalf("unexpected files left in tmpdir: %v", names)
255 func isAlpineLinux() bool {
256 if runtime.GOOS != "linux" {
259 fi, err := os.Lstat("/etc/alpine-release")
260 return err == nil && fi.Mode().IsRegular()
263 // The length of an mtime tick on this system. This is an estimate of
264 // how long we need to sleep to ensure that the mtime of two files is
266 // We used to try to be clever but that didn't always work (see golang.org/issue/12205).
267 var mtimeTick time.Duration = 1 * time.Second
269 // Manage a single run of the testgo binary.
270 type testgoData struct {
277 stdout, stderr bytes.Buffer
278 execDir string // dir for tg.run
281 // skipIfGccgo skips the test if using gccgo.
282 func skipIfGccgo(t *testing.T, msg string) {
283 if runtime.Compiler == "gccgo" {
284 t.Skipf("skipping test not supported on gccgo: %s", msg)
288 // testgo sets up for a test that runs testgo.
289 func testgo(t *testing.T) *testgoData {
291 testenv.MustHaveGoBuild(t)
292 testenv.SkipIfShortAndSlow(t)
294 return &testgoData{t: t}
297 // must gives a fatal error if err is not nil.
298 func (tg *testgoData) must(err error) {
305 // check gives a test non-fatal error if err is not nil.
306 func (tg *testgoData) check(err error) {
313 // parallel runs the test in parallel by calling t.Parallel.
314 func (tg *testgoData) parallel() {
317 tg.t.Fatal("internal testsuite error: call to parallel after run")
319 for _, e := range tg.env {
320 if strings.HasPrefix(e, "GOROOT=") || strings.HasPrefix(e, "GOPATH=") || strings.HasPrefix(e, "GOBIN=") {
321 val := e[strings.Index(e, "=")+1:]
322 if strings.HasPrefix(val, "testdata") || strings.HasPrefix(val, "./testdata") {
323 tg.t.Fatalf("internal testsuite error: call to parallel with testdata in environment (%s)", e)
331 // pwd returns the current directory.
332 func (tg *testgoData) pwd() string {
334 wd, err := os.Getwd()
336 tg.t.Fatalf("could not get working directory: %v", err)
341 // sleep sleeps for one tick, where a tick is a conservative estimate
342 // of how long it takes for a file modification to get a different
344 func (tg *testgoData) sleep() {
345 time.Sleep(mtimeTick)
348 // setenv sets an environment variable to use when running the test go
350 func (tg *testgoData) setenv(name, val string) {
352 if tg.inParallel && (name == "GOROOT" || name == "GOPATH" || name == "GOBIN") && (strings.HasPrefix(val, "testdata") || strings.HasPrefix(val, "./testdata")) {
353 tg.t.Fatalf("internal testsuite error: call to setenv with testdata (%s=%s) after parallel", name, val)
356 tg.env = append(tg.env, name+"="+val)
359 // unsetenv removes an environment variable.
360 func (tg *testgoData) unsetenv(name string) {
362 tg.env = append([]string(nil), os.Environ()...)
363 tg.env = append(tg.env, "GO111MODULE=off")
365 for i, v := range tg.env {
366 if strings.HasPrefix(v, name+"=") {
367 tg.env = append(tg.env[:i], tg.env[i+1:]...)
373 func (tg *testgoData) goTool() string {
377 // doRun runs the test go command, recording stdout and stderr and
378 // returning exit status.
379 func (tg *testgoData) doRun(args []string) error {
382 for _, arg := range args {
383 if strings.HasPrefix(arg, "testdata") || strings.HasPrefix(arg, "./testdata") {
384 tg.t.Fatal("internal testsuite error: parallel run using testdata")
390 for _, v := range tg.env {
391 if strings.HasPrefix(v, "GOROOT=") {
398 tg.setenv("GOROOT", testGOROOT)
401 tg.t.Logf("running testgo %v", args)
402 cmd := exec.Command(prog, args...)
406 cmd.Stdout = &tg.stdout
407 cmd.Stderr = &tg.stderr
410 if tg.stdout.Len() > 0 {
411 tg.t.Log("standard output:")
412 tg.t.Log(tg.stdout.String())
414 if tg.stderr.Len() > 0 {
415 tg.t.Log("standard error:")
416 tg.t.Log(tg.stderr.String())
422 // run runs the test go command, and expects it to succeed.
423 func (tg *testgoData) run(args ...string) {
425 if status := tg.doRun(args); status != nil {
427 tg.t.Logf("go %v failed unexpectedly in %s: %v", args, wd, status)
432 // runFail runs the test go command, and expects it to fail.
433 func (tg *testgoData) runFail(args ...string) {
435 if status := tg.doRun(args); status == nil {
436 tg.t.Fatal("testgo succeeded unexpectedly")
438 tg.t.Log("testgo failed as expected:", status)
442 // runGit runs a git command, and expects it to succeed.
443 func (tg *testgoData) runGit(dir string, args ...string) {
445 cmd := exec.Command("git", args...)
448 cmd.Stdout = &tg.stdout
449 cmd.Stderr = &tg.stderr
453 if tg.stdout.Len() > 0 {
454 tg.t.Log("git standard output:")
455 tg.t.Log(tg.stdout.String())
457 if tg.stderr.Len() > 0 {
458 tg.t.Log("git standard error:")
459 tg.t.Log(tg.stderr.String())
462 tg.t.Logf("git %v failed unexpectedly: %v", args, status)
467 // getStdout returns standard output of the testgo run as a string.
468 func (tg *testgoData) getStdout() string {
471 tg.t.Fatal("internal testsuite error: stdout called before run")
473 return tg.stdout.String()
476 // getStderr returns standard error of the testgo run as a string.
477 func (tg *testgoData) getStderr() string {
480 tg.t.Fatal("internal testsuite error: stdout called before run")
482 return tg.stderr.String()
485 // doGrepMatch looks for a regular expression in a buffer, and returns
486 // whether it is found. The regular expression is matched against
487 // each line separately, as with the grep command.
488 func (tg *testgoData) doGrepMatch(match string, b *bytes.Buffer) bool {
491 tg.t.Fatal("internal testsuite error: grep called before run")
493 re := regexp.MustCompile(match)
494 for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) {
502 // doGrep looks for a regular expression in a buffer and fails if it
503 // is not found. The name argument is the name of the output we are
504 // searching, "output" or "error". The msg argument is logged on
506 func (tg *testgoData) doGrep(match string, b *bytes.Buffer, name, msg string) {
508 if !tg.doGrepMatch(match, b) {
510 tg.t.Logf("pattern %v not found in standard %s", match, name)
515 // grepStdout looks for a regular expression in the test run's
516 // standard output and fails, logging msg, if it is not found.
517 func (tg *testgoData) grepStdout(match, msg string) {
519 tg.doGrep(match, &tg.stdout, "output", msg)
522 // grepStderr looks for a regular expression in the test run's
523 // standard error and fails, logging msg, if it is not found.
524 func (tg *testgoData) grepStderr(match, msg string) {
526 tg.doGrep(match, &tg.stderr, "error", msg)
529 // grepBoth looks for a regular expression in the test run's standard
530 // output or stand error and fails, logging msg, if it is not found.
531 func (tg *testgoData) grepBoth(match, msg string) {
533 if !tg.doGrepMatch(match, &tg.stdout) && !tg.doGrepMatch(match, &tg.stderr) {
535 tg.t.Logf("pattern %v not found in standard output or standard error", match)
540 // doGrepNot looks for a regular expression in a buffer and fails if
541 // it is found. The name and msg arguments are as for doGrep.
542 func (tg *testgoData) doGrepNot(match string, b *bytes.Buffer, name, msg string) {
544 if tg.doGrepMatch(match, b) {
546 tg.t.Logf("pattern %v found unexpectedly in standard %s", match, name)
551 // grepStdoutNot looks for a regular expression in the test run's
552 // standard output and fails, logging msg, if it is found.
553 func (tg *testgoData) grepStdoutNot(match, msg string) {
555 tg.doGrepNot(match, &tg.stdout, "output", msg)
558 // grepStderrNot looks for a regular expression in the test run's
559 // standard error and fails, logging msg, if it is found.
560 func (tg *testgoData) grepStderrNot(match, msg string) {
562 tg.doGrepNot(match, &tg.stderr, "error", msg)
565 // grepBothNot looks for a regular expression in the test run's
566 // standard output or standard error and fails, logging msg, if it is
568 func (tg *testgoData) grepBothNot(match, msg string) {
570 if tg.doGrepMatch(match, &tg.stdout) || tg.doGrepMatch(match, &tg.stderr) {
572 tg.t.Fatalf("pattern %v found unexpectedly in standard output or standard error", match)
576 // doGrepCount counts the number of times a regexp is seen in a buffer.
577 func (tg *testgoData) doGrepCount(match string, b *bytes.Buffer) int {
580 tg.t.Fatal("internal testsuite error: doGrepCount called before run")
582 re := regexp.MustCompile(match)
584 for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) {
592 // grepCountBoth returns the number of times a regexp is seen in both
593 // standard output and standard error.
594 func (tg *testgoData) grepCountBoth(match string) int {
596 return tg.doGrepCount(match, &tg.stdout) + tg.doGrepCount(match, &tg.stderr)
599 // creatingTemp records that the test plans to create a temporary file
600 // or directory. If the file or directory exists already, it will be
601 // removed. When the test completes, the file or directory will be
602 // removed if it exists.
603 func (tg *testgoData) creatingTemp(path string) {
605 if filepath.IsAbs(path) && !strings.HasPrefix(path, tg.tempdir) {
606 tg.t.Fatalf("internal testsuite error: creatingTemp(%q) with absolute path not in temporary directory", path)
608 tg.must(robustio.RemoveAll(path))
609 tg.temps = append(tg.temps, path)
612 // makeTempdir makes a temporary directory for a run of testgo. If
613 // the temporary directory was already created, this does nothing.
614 func (tg *testgoData) makeTempdir() {
616 if tg.tempdir == "" {
618 tg.tempdir, err = os.MkdirTemp("", "gotest")
623 // tempFile adds a temporary file for a run of testgo.
624 func (tg *testgoData) tempFile(path, contents string) {
627 tg.must(os.MkdirAll(filepath.Join(tg.tempdir, filepath.Dir(path)), 0755))
628 bytes := []byte(contents)
629 if strings.HasSuffix(path, ".go") {
630 formatted, err := format.Source(bytes)
635 tg.must(os.WriteFile(filepath.Join(tg.tempdir, path), bytes, 0644))
638 // tempDir adds a temporary directory for a run of testgo.
639 func (tg *testgoData) tempDir(path string) {
642 if err := os.MkdirAll(filepath.Join(tg.tempdir, path), 0755); err != nil && !os.IsExist(err) {
647 // path returns the absolute pathname to file with the temporary
649 func (tg *testgoData) path(name string) string {
651 if tg.tempdir == "" {
652 tg.t.Fatalf("internal testsuite error: path(%q) with no tempdir", name)
657 return filepath.Join(tg.tempdir, name)
660 // mustExist fails if path does not exist.
661 func (tg *testgoData) mustExist(path string) {
663 if _, err := os.Stat(path); err != nil {
664 if os.IsNotExist(err) {
665 tg.t.Fatalf("%s does not exist but should", path)
667 tg.t.Fatalf("%s stat failed: %v", path, err)
671 // mustNotExist fails if path exists.
672 func (tg *testgoData) mustNotExist(path string) {
674 if _, err := os.Stat(path); err == nil || !os.IsNotExist(err) {
675 tg.t.Fatalf("%s exists but should not (%v)", path, err)
679 // mustHaveContent succeeds if filePath is a path to a file,
680 // and that file is readable and not empty.
681 func (tg *testgoData) mustHaveContent(filePath string) {
682 tg.mustExist(filePath)
683 f, err := os.Stat(filePath)
688 tg.t.Fatalf("expected %s to have data, but is empty", filePath)
692 // wantExecutable fails with msg if path is not executable.
693 func (tg *testgoData) wantExecutable(path, msg string) {
695 if st, err := os.Stat(path); err != nil {
696 if !os.IsNotExist(err) {
701 if runtime.GOOS != "windows" && st.Mode()&0111 == 0 {
702 tg.t.Fatalf("binary %s exists but is not executable", path)
707 // isStale reports whether pkg is stale, and why
708 func (tg *testgoData) isStale(pkg string) (bool, string) {
710 tg.run("list", "-f", "{{.Stale}}:{{.StaleReason}}", pkg)
711 v := strings.TrimSpace(tg.getStdout())
712 f := strings.SplitN(v, ":", 2)
721 tg.t.Fatalf("unexpected output checking staleness of package %v: %v", pkg, v)
725 // wantStale fails with msg if pkg is not stale.
726 func (tg *testgoData) wantStale(pkg, reason, msg string) {
728 stale, why := tg.isStale(pkg)
732 // We always accept the reason as being "not installed but
733 // available in build cache", because when that is the case go
734 // list doesn't try to sort out the underlying reason why the
735 // package is not installed.
736 if reason == "" && why != "" || !strings.Contains(why, reason) && !strings.Contains(why, "not installed but available in build cache") {
737 tg.t.Errorf("wrong reason for Stale=true: %q, want %q", why, reason)
741 // wantNotStale fails with msg if pkg is stale.
742 func (tg *testgoData) wantNotStale(pkg, reason, msg string) {
744 stale, why := tg.isStale(pkg)
748 if reason == "" && why != "" || !strings.Contains(why, reason) {
749 tg.t.Errorf("wrong reason for Stale=false: %q, want %q", why, reason)
753 // If -testwork is specified, the test prints the name of the temp directory
754 // and does not remove it when done, so that a programmer can
755 // poke at the test file tree afterward.
756 var testWork = flag.Bool("testwork", false, "")
758 // cleanup cleans up a test that runs testgo.
759 func (tg *testgoData) cleanup() {
762 tg.t.Logf("TESTWORK=%s\n", tg.path("."))
765 for _, path := range tg.temps {
766 tg.check(removeAll(path))
768 if tg.tempdir != "" {
769 tg.check(removeAll(tg.tempdir))
773 func removeAll(dir string) error {
774 // module cache has 0444 directories;
775 // make them writable in order to remove content.
776 filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error {
777 // chmod not only directories, but also things that we couldn't even stat
778 // due to permission errors: they may also be unreadable directories.
779 if err != nil || info.IsDir() {
784 return robustio.RemoveAll(dir)
787 // failSSH puts an ssh executable in the PATH that always fails.
788 // This is to stub out uses of ssh by go get.
789 func (tg *testgoData) failSSH() {
791 wd, err := os.Getwd()
795 fail := filepath.Join(wd, "testdata/failssh")
796 tg.setenv("PATH", fmt.Sprintf("%v%c%v", fail, filepath.ListSeparator, os.Getenv("PATH")))
799 func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
801 t.Skip("skipping lengthy test in short mode")
808 // Copy the runtime packages into a temporary GOROOT
809 // so that we can change files.
810 for _, copydir := range []string{
813 "src/internal/bytealg",
815 "src/internal/goarch",
816 "src/internal/goexperiment",
820 filepath.Join("pkg", runtime.GOOS+"_"+runtime.GOARCH),
821 filepath.Join("pkg/tool", runtime.GOOS+"_"+runtime.GOARCH),
824 srcdir := filepath.Join(testGOROOT, copydir)
825 tg.tempDir(filepath.Join("goroot", copydir))
826 err := filepath.WalkDir(srcdir,
827 func(path string, info fs.DirEntry, err error) error {
834 srcrel, err := filepath.Rel(srcdir, path)
838 dest := filepath.Join("goroot", copydir, srcrel)
839 data, err := os.ReadFile(path)
843 tg.tempFile(dest, string(data))
844 if strings.Contains(copydir, filepath.Join("pkg", "tool")) {
845 os.Chmod(tg.path(dest), 0777)
853 tg.setenv("GOROOT", tg.path("goroot"))
855 addVar := func(name string, idx int) (restore func()) {
856 data, err := os.ReadFile(name)
861 data = append(data, fmt.Sprintf("var DummyUnusedVar%d bool\n", idx)...)
862 if err := os.WriteFile(name, append(data, '\n'), 0666); err != nil {
867 if err := os.WriteFile(name, old, 0666); err != nil {
873 // Every main package depends on the "runtime".
874 tg.tempFile("d1/src/p1/p1.go", `package main; func main(){}`)
875 tg.setenv("GOPATH", tg.path("d1"))
876 // Pass -i flag to rebuild everything outdated.
877 tg.run("install", "-i", "p1")
878 tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, before any changes")
880 // Changing mtime of runtime/internal/sys/sys.go
881 // should have no effect: only the content matters.
882 // In fact this should be true even outside a release branch.
883 sys := tg.path("goroot/src/runtime/internal/sys/sys.go")
885 restore := addVar(sys, 0)
887 tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after updating mtime of runtime/internal/sys/sys.go")
889 // But changing content of any file should have an effect.
890 // Previously zversion.go was the only one that mattered;
891 // now they all matter, so keep using sys.go.
892 restore = addVar(sys, 1)
894 tg.wantStale("p1", "stale dependency: runtime/internal/sys", "./testgo list claims p1 is NOT stale, incorrectly, after changing sys.go")
896 tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after changing back to old release")
898 tg.wantStale("p1", "stale dependency: runtime", "./testgo list claims p1 is NOT stale, incorrectly, after changing sys.go again")
899 tg.run("install", "-i", "p1")
900 tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with new release")
902 // Restore to "old" release.
904 tg.wantStale("p1", "stale dependency: runtime/internal/sys", "./testgo list claims p1 is NOT stale, incorrectly, after restoring sys.go")
905 tg.run("install", "-i", "p1")
906 tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with old release")
909 // cmd/go: custom import path checking should not apply to Go packages without import comment.
910 func TestIssue10952(t *testing.T) {
911 testenv.MustHaveExternalNetwork(t)
912 testenv.MustHaveExecPath(t, "git")
918 tg.setenv("GOPATH", tg.path("."))
919 const importPath = "github.com/zombiezen/go-get-issue-10952"
920 tg.run("get", "-d", "-u", importPath)
921 repoDir := tg.path("src/" + importPath)
922 tg.runGit(repoDir, "remote", "set-url", "origin", "https://"+importPath+".git")
923 tg.run("get", "-d", "-u", importPath)
926 func TestIssue16471(t *testing.T) {
927 testenv.MustHaveExternalNetwork(t)
928 testenv.MustHaveExecPath(t, "git")
934 tg.setenv("GOPATH", tg.path("."))
935 tg.must(os.MkdirAll(tg.path("src/rsc.io/go-get-issue-10952"), 0755))
936 tg.runGit(tg.path("src/rsc.io"), "clone", "https://github.com/zombiezen/go-get-issue-10952")
937 tg.runFail("get", "-u", "rsc.io/go-get-issue-10952")
938 tg.grepStderr("rsc.io/go-get-issue-10952 is a custom import path for https://github.com/rsc/go-get-issue-10952, but .* is checked out from https://github.com/zombiezen/go-get-issue-10952", "did not detect updated import path")
941 // Test git clone URL that uses SCP-like syntax and custom import path checking.
942 func TestIssue11457(t *testing.T) {
943 testenv.MustHaveExternalNetwork(t)
944 testenv.MustHaveExecPath(t, "git")
950 tg.setenv("GOPATH", tg.path("."))
951 const importPath = "rsc.io/go-get-issue-11457"
952 tg.run("get", "-d", "-u", importPath)
953 repoDir := tg.path("src/" + importPath)
954 tg.runGit(repoDir, "remote", "set-url", "origin", "git@github.com:rsc/go-get-issue-11457")
956 // At this time, custom import path checking compares remotes verbatim (rather than
957 // just the host and path, skipping scheme and user), so we expect go get -u to fail.
958 // However, the goal of this test is to verify that gitRemoteRepo correctly parsed
959 // the SCP-like syntax, and we expect it to appear in the error message.
960 tg.runFail("get", "-d", "-u", importPath)
961 want := " is checked out from ssh://git@github.com/rsc/go-get-issue-11457"
962 if !strings.HasSuffix(strings.TrimSpace(tg.getStderr()), want) {
963 t.Error("expected clone URL to appear in stderr")
967 func TestGetGitDefaultBranch(t *testing.T) {
968 testenv.MustHaveExternalNetwork(t)
969 testenv.MustHaveExecPath(t, "git")
975 tg.setenv("GOPATH", tg.path("."))
977 // This repo has two branches, master and another-branch.
978 // The another-branch is the default that you get from 'git clone'.
979 // The go get command variants should not override this.
980 const importPath = "github.com/rsc/go-get-default-branch"
982 tg.run("get", "-d", importPath)
983 repoDir := tg.path("src/" + importPath)
984 tg.runGit(repoDir, "branch", "--contains", "HEAD")
985 tg.grepStdout(`\* another-branch`, "not on correct default branch")
987 tg.run("get", "-d", "-u", importPath)
988 tg.runGit(repoDir, "branch", "--contains", "HEAD")
989 tg.grepStdout(`\* another-branch`, "not on correct default branch")
992 // Security issue. Don't disable. See golang.org/issue/22125.
993 func TestAccidentalGitCheckout(t *testing.T) {
994 testenv.MustHaveExternalNetwork(t)
995 testenv.MustHaveExecPath(t, "git")
996 testenv.MustHaveExecPath(t, "svn")
1003 tg.setenv("GOPATH", tg.path("."))
1005 tg.runFail("get", "-u", "vcs-test.golang.org/go/test1-svn-git")
1006 tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason")
1008 if _, err := os.Stat(tg.path("SrC")); err == nil {
1009 // This case only triggers on a case-insensitive file system.
1010 tg.runFail("get", "-u", "vcs-test.golang.org/go/test2-svn-git/test2main")
1011 tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason")
1015 func TestPackageMainTestCompilerFlags(t *testing.T) {
1020 tg.setenv("GOPATH", tg.path("."))
1021 tg.tempFile("src/p1/p1.go", "package main\n")
1022 tg.tempFile("src/p1/p1_test.go", "package main\nimport \"testing\"\nfunc Test(t *testing.T){}\n")
1023 tg.run("test", "-c", "-n", "p1")
1024 tg.grepBothNot(`([\\/]compile|gccgo).* (-p main|-fgo-pkgpath=main).*p1\.go`, "should not have run compile -p main p1.go")
1025 tg.grepStderr(`([\\/]compile|gccgo).* (-p p1|-fgo-pkgpath=p1).*p1\.go`, "should have run compile -p p1 p1.go")
1029 func TestGoTestWithPackageListedMultipleTimes(t *testing.T) {
1034 tg.run("test", "errors", "errors", "errors", "errors", "errors")
1035 if strings.Contains(strings.TrimSpace(tg.getStdout()), "\n") {
1036 t.Error("go test errors errors errors errors errors tested the same package multiple times")
1040 func TestGoListHasAConsistentOrder(t *testing.T) {
1045 tg.run("list", "std")
1046 first := tg.getStdout()
1047 tg.run("list", "std")
1048 if first != tg.getStdout() {
1049 t.Error("go list std ordering is inconsistent")
1053 func TestGoListStdDoesNotIncludeCommands(t *testing.T) {
1058 tg.run("list", "std")
1059 tg.grepStdoutNot("cmd/", "go list std shows commands")
1062 func TestGoListCmdOnlyShowsCommands(t *testing.T) {
1063 skipIfGccgo(t, "gccgo does not have GOROOT")
1068 tg.run("list", "cmd")
1069 out := strings.TrimSpace(tg.getStdout())
1070 for _, line := range strings.Split(out, "\n") {
1071 if !strings.Contains(line, "cmd/") {
1072 t.Error("go list cmd shows non-commands")
1078 func TestGoListDeps(t *testing.T) {
1082 tg.tempDir("src/p1/p2/p3/p4")
1083 tg.setenv("GOPATH", tg.path("."))
1084 tg.tempFile("src/p1/p.go", "package p1\nimport _ \"p1/p2\"\n")
1085 tg.tempFile("src/p1/p2/p.go", "package p2\nimport _ \"p1/p2/p3\"\n")
1086 tg.tempFile("src/p1/p2/p3/p.go", "package p3\nimport _ \"p1/p2/p3/p4\"\n")
1087 tg.tempFile("src/p1/p2/p3/p4/p.go", "package p4\n")
1088 tg.run("list", "-f", "{{.Deps}}", "p1")
1089 tg.grepStdout("p1/p2/p3/p4", "Deps(p1) does not mention p4")
1091 tg.run("list", "-deps", "p1")
1092 tg.grepStdout("p1/p2/p3/p4", "-deps p1 does not mention p4")
1094 if runtime.Compiler != "gccgo" {
1095 // Check the list is in dependency order.
1096 tg.run("list", "-deps", "math")
1097 want := "internal/cpu\nunsafe\nmath/bits\nmath\n"
1098 out := tg.stdout.String()
1099 if !strings.Contains(out, "internal/cpu") {
1100 // Some systems don't use internal/cpu.
1101 want = "unsafe\nmath/bits\nmath\n"
1103 if tg.stdout.String() != want {
1104 t.Fatalf("list -deps math: wrong order\nhave %q\nwant %q", tg.stdout.String(), want)
1109 func TestGoListTest(t *testing.T) {
1110 skipIfGccgo(t, "gccgo does not have standard packages")
1115 tg.setenv("GOCACHE", tg.tempdir)
1117 tg.run("list", "-test", "-deps", "sort")
1118 tg.grepStdout(`^sort.test$`, "missing test main")
1119 tg.grepStdout(`^sort$`, "missing real sort")
1120 tg.grepStdout(`^sort \[sort.test\]$`, "missing test copy of sort")
1121 tg.grepStdout(`^testing \[sort.test\]$`, "missing test copy of testing")
1122 tg.grepStdoutNot(`^testing$`, "unexpected real copy of testing")
1124 tg.run("list", "-test", "sort")
1125 tg.grepStdout(`^sort.test$`, "missing test main")
1126 tg.grepStdout(`^sort$`, "missing real sort")
1127 tg.grepStdout(`^sort \[sort.test\]$`, "unexpected test copy of sort")
1128 tg.grepStdoutNot(`^testing \[sort.test\]$`, "unexpected test copy of testing")
1129 tg.grepStdoutNot(`^testing$`, "unexpected real copy of testing")
1131 tg.run("list", "-test", "cmd/dist", "cmd/doc")
1132 tg.grepStdout(`^cmd/dist$`, "missing cmd/dist")
1133 tg.grepStdout(`^cmd/doc$`, "missing cmd/doc")
1134 tg.grepStdout(`^cmd/doc\.test$`, "missing cmd/doc test")
1135 tg.grepStdoutNot(`^cmd/dist\.test$`, "unexpected cmd/dist test")
1136 tg.grepStdoutNot(`^testing`, "unexpected testing")
1138 tg.run("list", "-test", "runtime/cgo")
1139 tg.grepStdout(`^runtime/cgo$`, "missing runtime/cgo")
1141 tg.run("list", "-deps", "-f", "{{if .DepOnly}}{{.ImportPath}}{{end}}", "sort")
1142 tg.grepStdout(`^internal/reflectlite$`, "missing internal/reflectlite")
1143 tg.grepStdoutNot(`^sort`, "unexpected sort")
1146 func TestGoListCompiledCgo(t *testing.T) {
1152 tg.setenv("GOCACHE", tg.tempdir)
1154 tg.run("list", "-f", `{{join .CgoFiles "\n"}}`, "net")
1155 if tg.stdout.String() == "" {
1156 t.Skip("net does not use cgo")
1158 if strings.Contains(tg.stdout.String(), tg.tempdir) {
1159 t.Fatalf(".CgoFiles unexpectedly mentioned cache %s", tg.tempdir)
1161 tg.run("list", "-compiled", "-f", `{{.Dir}}{{"\n"}}{{join .CompiledGoFiles "\n"}}`, "net")
1162 if !strings.Contains(tg.stdout.String(), tg.tempdir) {
1163 t.Fatalf(".CompiledGoFiles with -compiled did not mention cache %s", tg.tempdir)
1166 for _, file := range strings.Split(tg.stdout.String(), "\n") {
1174 if !strings.Contains(file, "/") && !strings.Contains(file, `\`) {
1175 file = filepath.Join(dir, file)
1177 if _, err := os.Stat(file); err != nil {
1178 t.Fatalf("cannot find .CompiledGoFiles result %s: %v", file, err)
1183 func TestGoListExport(t *testing.T) {
1184 skipIfGccgo(t, "gccgo does not have standard packages")
1189 tg.setenv("GOCACHE", tg.tempdir)
1191 tg.run("list", "-f", "{{.Export}}", "strings")
1192 if tg.stdout.String() != "" {
1193 t.Fatalf(".Export without -export unexpectedly set")
1195 tg.run("list", "-export", "-f", "{{.Export}}", "strings")
1196 file := strings.TrimSpace(tg.stdout.String())
1198 t.Fatalf(".Export with -export was empty")
1200 if _, err := os.Stat(file); err != nil {
1201 t.Fatalf("cannot find .Export result %s: %v", file, err)
1204 tg.run("list", "-export", "-f", "{{.BuildID}}", "strings")
1205 buildID := strings.TrimSpace(tg.stdout.String())
1207 t.Fatalf(".BuildID with -export was empty")
1210 tg.run("tool", "buildid", file)
1211 toolBuildID := strings.TrimSpace(tg.stdout.String())
1212 if buildID != toolBuildID {
1213 t.Fatalf(".BuildID with -export %q disagrees with 'go tool buildid' %q", buildID, toolBuildID)
1217 // Issue 4096. Validate the output of unsuccessful go install foo/quxx.
1218 func TestUnsuccessfulGoInstallShouldMentionMissingPackage(t *testing.T) {
1222 tg.runFail("install", "foo/quxx")
1223 if tg.grepCountBoth(`cannot find package "foo/quxx" in any of`) != 1 {
1224 t.Error(`go install foo/quxx expected error: .*cannot find package "foo/quxx" in any of`)
1228 func TestGOROOTSearchFailureReporting(t *testing.T) {
1232 tg.runFail("install", "foo/quxx")
1233 if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("foo", "quxx"))+` \(from \$GOROOT\)$`) != 1 {
1234 t.Error(`go install foo/quxx expected error: .*foo/quxx (from $GOROOT)`)
1238 func TestMultipleGOPATHEntriesReportedSeparately(t *testing.T) {
1242 sep := string(filepath.ListSeparator)
1243 tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
1244 tg.runFail("install", "foo/quxx")
1245 if tg.grepCountBoth(`testdata[/\\].[/\\]src[/\\]foo[/\\]quxx`) != 2 {
1246 t.Error(`go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)\n.*testdata/b/src/foo/quxx`)
1250 // Test (from $GOPATH) annotation is reported for the first GOPATH entry,
1251 func TestMentionGOPATHInFirstGOPATHEntry(t *testing.T) {
1255 sep := string(filepath.ListSeparator)
1256 tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
1257 tg.runFail("install", "foo/quxx")
1258 if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("testdata", "a", "src", "foo", "quxx"))+` \(from \$GOPATH\)$`) != 1 {
1259 t.Error(`go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)`)
1263 // but not on the second.
1264 func TestMentionGOPATHNotOnSecondEntry(t *testing.T) {
1268 sep := string(filepath.ListSeparator)
1269 tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
1270 tg.runFail("install", "foo/quxx")
1271 if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("testdata", "b", "src", "foo", "quxx"))+`$`) != 1 {
1272 t.Error(`go install foo/quxx expected error: .*testdata/b/src/foo/quxx`)
1276 func homeEnvName() string {
1277 switch runtime.GOOS {
1279 return "USERPROFILE"
1287 func tempEnvName() string {
1288 switch runtime.GOOS {
1292 return "TMPDIR" // actually plan 9 doesn't have one at all but this is fine
1298 func TestDefaultGOPATH(t *testing.T) {
1302 tg.tempDir("home/go")
1303 tg.setenv(homeEnvName(), tg.path("home"))
1305 tg.run("env", "GOPATH")
1306 tg.grepStdout(regexp.QuoteMeta(tg.path("home/go")), "want GOPATH=$HOME/go")
1308 tg.setenv("GOROOT", tg.path("home/go"))
1309 tg.run("env", "GOPATH")
1310 tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go")
1312 tg.setenv("GOROOT", tg.path("home/go")+"/")
1313 tg.run("env", "GOPATH")
1314 tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go/")
1317 func TestDefaultGOPATHGet(t *testing.T) {
1318 testenv.MustHaveExternalNetwork(t)
1319 testenv.MustHaveExecPath(t, "git")
1324 tg.setenv("GOPATH", "")
1326 tg.setenv(homeEnvName(), tg.path("home"))
1328 // warn for creating directory
1329 tg.run("get", "-v", "github.com/golang/example/hello")
1330 tg.grepStderr("created GOPATH="+regexp.QuoteMeta(tg.path("home/go"))+"; see 'go help gopath'", "did not create GOPATH")
1332 // no warning if directory already exists
1333 tg.must(robustio.RemoveAll(tg.path("home/go")))
1334 tg.tempDir("home/go")
1335 tg.run("get", "github.com/golang/example/hello")
1336 tg.grepStderrNot(".", "expected no output on standard error")
1338 // error if $HOME/go is a file
1339 tg.must(robustio.RemoveAll(tg.path("home/go")))
1340 tg.tempFile("home/go", "")
1341 tg.runFail("get", "github.com/golang/example/hello")
1342 tg.grepStderr(`mkdir .*[/\\]go: .*(not a directory|cannot find the path)`, "expected error because $HOME/go is a file")
1345 func TestDefaultGOPATHPrintedSearchList(t *testing.T) {
1349 tg.setenv("GOPATH", "")
1351 tg.setenv(homeEnvName(), tg.path("home"))
1353 tg.runFail("install", "github.com/golang/example/hello")
1354 tg.grepStderr(regexp.QuoteMeta(tg.path("home/go/src/github.com/golang/example/hello"))+`.*from \$GOPATH`, "expected default GOPATH")
1357 func TestLdflagsArgumentsWithSpacesIssue3941(t *testing.T) {
1358 skipIfGccgo(t, "gccgo does not support -ldflags -X")
1363 tg.tempFile("main.go", `package main
1368 tg.run("run", "-ldflags", `-X "main.extern=hello world"`, tg.path("main.go"))
1369 tg.grepStderr("^hello world", `ldflags -X "main.extern=hello world"' failed`)
1372 func TestLdFlagsLongArgumentsIssue42295(t *testing.T) {
1373 // Test the extremely long command line arguments that contain '\n' characters
1374 // get encoded and passed correctly.
1375 skipIfGccgo(t, "gccgo does not support -ldflags -X")
1380 tg.tempFile("main.go", `package main
1385 testStr := "test test test test test \n\\ "
1386 var buf bytes.Buffer
1387 for buf.Len() < sys.ExecArgLengthLimit+1 {
1388 buf.WriteString(testStr)
1390 tg.run("run", "-buildinfo=false", "-ldflags", fmt.Sprintf(`-X "main.extern=%s"`, buf.String()), tg.path("main.go"))
1391 if tg.stderr.String() != buf.String() {
1392 t.Errorf("strings differ")
1396 func TestGoTestDashCDashOControlsBinaryLocation(t *testing.T) {
1397 skipIfGccgo(t, "gccgo has no standard packages")
1403 tg.run("test", "-c", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
1404 tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -c -o myerrors.test did not create myerrors.test")
1407 func TestGoTestDashOWritesBinary(t *testing.T) {
1408 skipIfGccgo(t, "gccgo has no standard packages")
1414 tg.run("test", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
1415 tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -o myerrors.test did not create myerrors.test")
1418 func TestGoTestDashIDashOWritesBinary(t *testing.T) {
1419 skipIfGccgo(t, "gccgo has no standard packages")
1426 // don't let test -i overwrite runtime
1427 tg.wantNotStale("runtime", "", "must be non-stale before test -i")
1429 tg.run("test", "-v", "-i", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
1430 tg.grepBothNot("PASS|FAIL", "test should not have run")
1431 tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -o myerrors.test did not create myerrors.test")
1435 func TestInstallWithTags(t *testing.T) {
1441 tg.tempFile("src/example/a/main.go", `package main
1443 tg.tempFile("src/example/b/main.go", `// +build mytag
1447 tg.setenv("GOPATH", tg.path("."))
1448 tg.run("install", "-tags", "mytag", "example/a", "example/b")
1449 tg.wantExecutable(tg.path("bin/a"+exeSuffix), "go install example/a example/b did not install binaries")
1450 tg.wantExecutable(tg.path("bin/b"+exeSuffix), "go install example/a example/b did not install binaries")
1451 tg.must(os.Remove(tg.path("bin/a" + exeSuffix)))
1452 tg.must(os.Remove(tg.path("bin/b" + exeSuffix)))
1453 tg.run("install", "-tags", "mytag", "example/...")
1454 tg.wantExecutable(tg.path("bin/a"+exeSuffix), "go install example/... did not install binaries")
1455 tg.wantExecutable(tg.path("bin/b"+exeSuffix), "go install example/... did not install binaries")
1456 tg.run("list", "-tags", "mytag", "example/b...")
1457 if strings.TrimSpace(tg.getStdout()) != "example/b" {
1458 t.Error("go list example/b did not find example/b")
1462 // Issue 17451, 17662.
1463 func TestSymlinkWarning(t *testing.T) {
1468 tg.setenv("GOPATH", tg.path("."))
1470 tg.tempDir("src/example/xx")
1472 tg.tempFile("yy/zz/zz.go", "package zz\n")
1473 if err := os.Symlink(tg.path("yy"), tg.path("src/example/xx/yy")); err != nil {
1474 t.Skipf("symlink failed: %v", err)
1476 tg.run("list", "example/xx/z...")
1477 tg.grepStdoutNot(".", "list should not have matched anything")
1478 tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages")
1479 tg.grepStderrNot("symlink", "list should not have reported symlink")
1481 tg.run("list", "example/xx/...")
1482 tg.grepStdoutNot(".", "list should not have matched anything")
1483 tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages")
1484 tg.grepStderr("ignoring symlink", "list should have reported symlink")
1487 func TestCgoShowsFullPathNames(t *testing.T) {
1489 t.Skip("skipping because cgo not enabled")
1495 tg.tempFile("src/x/y/dirname/foo.go", `
1499 tg.setenv("GOPATH", tg.path("."))
1500 tg.runFail("build", "x/y/dirname")
1501 tg.grepBoth("x/y/dirname", "error did not use full path")
1504 func TestCgoHandlesWlORIGIN(t *testing.T) {
1507 t.Skip("skipping because cgo not enabled")
1513 tg.tempFile("src/origin/origin.go", `package origin
1514 // #cgo !darwin LDFLAGS: -Wl,-rpath,$ORIGIN
1517 func f() { C.f() }`)
1518 tg.setenv("GOPATH", tg.path("."))
1519 tg.run("build", "origin")
1522 func TestCgoPkgConfig(t *testing.T) {
1525 t.Skip("skipping because cgo not enabled")
1531 tg.run("env", "PKG_CONFIG")
1532 pkgConfig := strings.TrimSpace(tg.getStdout())
1533 testenv.MustHaveExecPath(t, pkgConfig)
1534 if out, err := exec.Command(pkgConfig, "--atleast-pkgconfig-version", "0.24").CombinedOutput(); err != nil {
1535 t.Skipf("%s --atleast-pkgconfig-version 0.24: %v\n%s", pkgConfig, err, out)
1538 // OpenBSD's pkg-config is strict about whitespace and only
1539 // supports backslash-escaped whitespace. It does not support
1540 // quotes, which the normal freedesktop.org pkg-config does
1541 // support. See https://man.openbsd.org/pkg-config.1
1542 tg.tempFile("foo.pc", `
1544 Description: The foo library
1546 Cflags: -Dhello=10 -Dworld=+32 -DDEFINED_FROM_PKG_CONFIG=hello\ world
1548 tg.tempFile("foo.go", `package main
1551 #cgo pkg-config: foo
1553 return DEFINED_FROM_PKG_CONFIG;
1560 if C.value() != 42 {
1561 println("value() =", C.value(), "wanted 42")
1566 tg.setenv("PKG_CONFIG_PATH", tg.path("."))
1567 tg.run("run", tg.path("foo.go"))
1570 func TestListTemplateContextFunction(t *testing.T) {
1572 for _, tt := range []struct {
1576 {"GOARCH", runtime.GOARCH},
1577 {"GOOS", runtime.GOOS},
1578 {"GOROOT", filepath.Clean(runtime.GOROOT())},
1579 {"GOPATH", os.Getenv("GOPATH")},
1581 {"UseAllFiles", ""},
1584 {"ReleaseTags", ""},
1585 {"InstallSuffix", ""},
1588 t.Run(tt.v, func(t *testing.T) {
1592 tmpl := "{{context." + tt.v + "}}"
1593 tg.run("list", "-f", tmpl)
1597 if got := strings.TrimSpace(tg.getStdout()); got != tt.want {
1598 t.Errorf("go list -f %q: got %q; want %q", tmpl, got, tt.want)
1604 // Test that you cannot use a local import in a package
1605 // accessed by a non-local import (found in a GOPATH/GOROOT).
1606 // See golang.org/issue/17475.
1607 func TestImportLocal(t *testing.T) {
1614 tg.tempFile("src/dir/x/x.go", `package x
1617 tg.setenv("GOPATH", tg.path("."))
1618 tg.run("build", "dir/x")
1620 // Ordinary import should work.
1621 tg.tempFile("src/dir/p0/p.go", `package p0
1625 tg.run("build", "dir/p0")
1627 // Relative import should not.
1628 tg.tempFile("src/dir/p1/p.go", `package p1
1632 tg.runFail("build", "dir/p1")
1633 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1635 // ... even in a test.
1636 tg.tempFile("src/dir/p2/p.go", `package p2
1638 tg.tempFile("src/dir/p2/p_test.go", `package p2
1642 func TestFoo(t *testing.T) {}
1644 tg.run("build", "dir/p2")
1645 tg.runFail("test", "dir/p2")
1646 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1648 // ... even in an xtest.
1649 tg.tempFile("src/dir/p2/p_test.go", `package p2_test
1653 func TestFoo(t *testing.T) {}
1655 tg.run("build", "dir/p2")
1656 tg.runFail("test", "dir/p2")
1657 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1659 // Relative import starting with ./ should not work either.
1660 tg.tempFile("src/dir/d.go", `package dir
1664 tg.runFail("build", "dir")
1665 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1667 // ... even in a test.
1668 tg.tempFile("src/dir/d.go", `package dir
1670 tg.tempFile("src/dir/d_test.go", `package dir
1674 func TestFoo(t *testing.T) {}
1676 tg.run("build", "dir")
1677 tg.runFail("test", "dir")
1678 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1680 // ... even in an xtest.
1681 tg.tempFile("src/dir/d_test.go", `package dir_test
1685 func TestFoo(t *testing.T) {}
1687 tg.run("build", "dir")
1688 tg.runFail("test", "dir")
1689 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1691 // Relative import plain ".." should not work.
1692 tg.tempFile("src/dir/x/y/y.go", `package dir
1696 tg.runFail("build", "dir/x/y")
1697 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1699 // ... even in a test.
1700 tg.tempFile("src/dir/x/y/y.go", `package y
1702 tg.tempFile("src/dir/x/y/y_test.go", `package y
1706 func TestFoo(t *testing.T) {}
1708 tg.run("build", "dir/x/y")
1709 tg.runFail("test", "dir/x/y")
1710 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1712 // ... even in an x test.
1713 tg.tempFile("src/dir/x/y/y_test.go", `package y_test
1717 func TestFoo(t *testing.T) {}
1719 tg.run("build", "dir/x/y")
1720 tg.runFail("test", "dir/x/y")
1721 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1723 // Relative import "." should not work.
1724 tg.tempFile("src/dir/x/xx.go", `package x
1728 tg.runFail("build", "dir/x")
1729 tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
1731 // ... even in a test.
1732 tg.tempFile("src/dir/x/xx.go", `package x
1734 tg.tempFile("src/dir/x/xx_test.go", `package x
1738 func TestFoo(t *testing.T) {}
1740 tg.run("build", "dir/x")
1741 tg.runFail("test", "dir/x")
1742 tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
1744 // ... even in an xtest.
1745 tg.tempFile("src/dir/x/xx.go", `package x
1747 tg.tempFile("src/dir/x/xx_test.go", `package x_test
1751 func TestFoo(t *testing.T) {}
1753 tg.run("build", "dir/x")
1754 tg.runFail("test", "dir/x")
1755 tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
1758 func TestGoInstallPkgdir(t *testing.T) {
1759 skipIfGccgo(t, "gccgo has no standard packages")
1767 tg.run("install", "-pkgdir", pkg, "sync")
1768 tg.mustExist(filepath.Join(pkg, "sync.a"))
1769 tg.mustNotExist(filepath.Join(pkg, "sync/atomic.a"))
1770 tg.run("install", "-i", "-pkgdir", pkg, "sync")
1771 tg.mustExist(filepath.Join(pkg, "sync.a"))
1772 tg.mustExist(filepath.Join(pkg, "sync/atomic.a"))
1776 func TestParallelTest(t *testing.T) {
1782 const testSrc = `package package_test
1786 func TestTest(t *testing.T) {
1788 tg.tempFile("src/p1/p1_test.go", strings.Replace(testSrc, "package_test", "p1_test", 1))
1789 tg.tempFile("src/p2/p2_test.go", strings.Replace(testSrc, "package_test", "p2_test", 1))
1790 tg.tempFile("src/p3/p3_test.go", strings.Replace(testSrc, "package_test", "p3_test", 1))
1791 tg.tempFile("src/p4/p4_test.go", strings.Replace(testSrc, "package_test", "p4_test", 1))
1792 tg.setenv("GOPATH", tg.path("."))
1793 tg.run("test", "-p=4", "p1", "p2", "p3", "p4")
1796 func TestBinaryOnlyPackages(t *testing.T) {
1803 tg.setenv("GOPATH", tg.path("."))
1805 tg.tempFile("src/p1/p1.go", `//go:binary-only-package
1809 tg.wantStale("p1", "binary-only packages are no longer supported", "p1 is binary-only, and this message should always be printed")
1810 tg.runFail("install", "p1")
1811 tg.grepStderr("binary-only packages are no longer supported", "did not report attempt to compile binary-only package")
1813 tg.tempFile("src/p1/p1.go", `
1816 func F(b bool) { fmt.Printf("hello from p1\n"); if b { F(false) } }
1818 tg.run("install", "p1")
1819 os.Remove(tg.path("src/p1/p1.go"))
1820 tg.mustNotExist(tg.path("src/p1/p1.go"))
1822 tg.tempFile("src/p2/p2.go", `//go:binary-only-packages-are-not-great
1826 func F() { p1.F(true) }
1828 tg.runFail("install", "p2")
1829 tg.grepStderr("no Go files", "did not complain about missing sources")
1831 tg.tempFile("src/p1/missing.go", `//go:binary-only-package
1837 tg.wantStale("p1", "binary-only package", "should NOT want to rebuild p1 (first)")
1838 tg.runFail("install", "p2")
1839 tg.grepStderr("p1: binary-only packages are no longer supported", "did not report error for binary-only p1")
1841 tg.run("list", "-deps", "-f", "{{.ImportPath}}: {{.BinaryOnly}}", "p2")
1842 tg.grepStdout("p1: true", "p1 not listed as BinaryOnly")
1843 tg.grepStdout("p2: false", "p2 listed as BinaryOnly")
1846 // Issue 16050 and 21884.
1847 func TestLinkSysoFiles(t *testing.T) {
1848 if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
1849 t.Skip("not linux/amd64")
1855 tg.tempDir("src/syso")
1856 tg.tempFile("src/syso/a.syso", ``)
1857 tg.tempFile("src/syso/b.go", `package syso`)
1858 tg.setenv("GOPATH", tg.path("."))
1860 // We should see the .syso file regardless of the setting of
1863 tg.setenv("CGO_ENABLED", "1")
1864 tg.run("list", "-f", "{{.SysoFiles}}", "syso")
1865 tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=1")
1867 tg.setenv("CGO_ENABLED", "0")
1868 tg.run("list", "-f", "{{.SysoFiles}}", "syso")
1869 tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=0")
1871 tg.setenv("CGO_ENABLED", "1")
1872 tg.run("list", "-msan", "-f", "{{.SysoFiles}}", "syso")
1873 tg.grepStdoutNot("a.syso", "unexpected syso file with -msan")
1877 func TestGenerateUsesBuildContext(t *testing.T) {
1878 if runtime.GOOS == "windows" {
1879 t.Skip("this test won't run under Windows")
1885 tg.tempDir("src/gen")
1886 tg.tempFile("src/gen/gen.go", "package gen\n//go:generate echo $GOOS $GOARCH\n")
1887 tg.setenv("GOPATH", tg.path("."))
1889 tg.setenv("GOOS", "linux")
1890 tg.setenv("GOARCH", "amd64")
1891 tg.run("generate", "gen")
1892 tg.grepStdout("linux amd64", "unexpected GOOS/GOARCH combination")
1894 tg.setenv("GOOS", "darwin")
1895 tg.setenv("GOARCH", "arm64")
1896 tg.run("generate", "gen")
1897 tg.grepStdout("darwin arm64", "unexpected GOOS/GOARCH combination")
1900 func TestGoEnv(t *testing.T) {
1904 tg.setenv("GOOS", "freebsd") // to avoid invalid pair errors
1905 tg.setenv("GOARCH", "arm")
1906 tg.run("env", "GOARCH")
1907 tg.grepStdout("^arm$", "GOARCH not honored")
1909 tg.run("env", "GCCGO")
1910 tg.grepStdout(".", "GCCGO unexpectedly empty")
1912 tg.run("env", "CGO_CFLAGS")
1913 tg.grepStdout(".", "default CGO_CFLAGS unexpectedly empty")
1915 tg.setenv("CGO_CFLAGS", "-foobar")
1916 tg.run("env", "CGO_CFLAGS")
1917 tg.grepStdout("^-foobar$", "CGO_CFLAGS not honored")
1919 tg.setenv("CC", "gcc -fmust -fgo -ffaster")
1921 tg.grepStdout("gcc", "CC not found")
1922 tg.run("env", "GOGCCFLAGS")
1923 tg.grepStdout("-ffaster", "CC arguments not found")
1925 tg.run("env", "GOVERSION")
1926 envVersion := strings.TrimSpace(tg.stdout.String())
1929 cmdVersion := strings.TrimSpace(tg.stdout.String())
1931 // If 'go version' is "go version <version> <goos>/<goarch>", then
1932 // 'go env GOVERSION' is just "<version>".
1933 if cmdVersion == envVersion || !strings.Contains(cmdVersion, envVersion) {
1934 t.Fatalf("'go env GOVERSION' %q should be a shorter substring of 'go version' %q", envVersion, cmdVersion)
1939 noMatchesPattern = `(?m)^ok.*\[no tests to run\]`
1940 okPattern = `(?m)^ok`
1944 func TestLdBindNow(t *testing.T) {
1948 tg.setenv("LD_BIND_NOW", "1")
1953 // This is really a cmd/asm issue but this is a convenient place to test it.
1954 func TestConcurrentAsm(t *testing.T) {
1955 skipIfGccgo(t, "gccgo does not use cmd/asm")
1959 asm := `DATA ·constants<>+0x0(SB)/8,$0
1960 GLOBL ·constants<>(SB),8,$8
1962 tg.tempFile("go/src/p/a.s", asm)
1963 tg.tempFile("go/src/p/b.s", asm)
1964 tg.tempFile("go/src/p/p.go", `package p`)
1965 tg.setenv("GOPATH", tg.path("go"))
1966 tg.run("build", "p")
1970 func TestFFLAGS(t *testing.T) {
1972 t.Skip("skipping because cgo not enabled")
1979 tg.tempFile("p/src/p/main.go", `package main
1980 // #cgo FFLAGS: -no-such-fortran-flag
1984 tg.tempFile("p/src/p/a.f", `! comment`)
1985 tg.setenv("GOPATH", tg.path("p"))
1987 // This should normally fail because we are passing an unknown flag,
1988 // but issue #19080 points to Fortran compilers that succeed anyhow.
1989 // To work either way we call doRun directly rather than run or runFail.
1990 tg.doRun([]string{"build", "-x", "p"})
1992 tg.grepStderr("no-such-fortran-flag", `missing expected "-no-such-fortran-flag"`)
1996 // This is really a cmd/link issue but this is a convenient place to test it.
1997 func TestDuplicateGlobalAsmSymbols(t *testing.T) {
1998 skipIfGccgo(t, "gccgo does not use cmd/asm")
2000 if runtime.GOARCH != "386" && runtime.GOARCH != "amd64" {
2001 t.Skipf("skipping test on %s", runtime.GOARCH)
2004 t.Skip("skipping because cgo not enabled")
2012 #include "textflag.h"
2014 DATA sym<>+0x0(SB)/8,$0
2015 GLOBL sym<>(SB),(NOPTR+RODATA),$8
2017 TEXT ·Data(SB),NOSPLIT,$0
2022 tg.tempFile("go/src/a/a.s", asm)
2023 tg.tempFile("go/src/a/a.go", `package a; func Data() uint8`)
2024 tg.tempFile("go/src/b/b.s", asm)
2025 tg.tempFile("go/src/b/b.go", `package b; func Data() uint8`)
2026 tg.tempFile("go/src/p/p.go", `
2032 _ = a.Data() + b.Data()
2035 tg.setenv("GOPATH", tg.path("go"))
2036 exe := tg.path("p.exe")
2037 tg.creatingTemp(exe)
2038 tg.run("build", "-o", exe, "p")
2041 func copyFile(src, dst string, perm fs.FileMode) error {
2042 sf, err := os.Open(src)
2048 df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
2053 _, err = io.Copy(df, sf)
2061 func TestNeedVersion(t *testing.T) {
2062 skipIfGccgo(t, "gccgo does not use cmd/compile")
2066 tg.tempFile("goversion.go", `package main; func main() {}`)
2067 path := tg.path("goversion.go")
2068 tg.setenv("TESTGO_VERSION", "go1.testgo")
2069 tg.runFail("run", path)
2070 tg.grepStderr("compile", "does not match go tool version")
2073 func TestBuildmodePIE(t *testing.T) {
2074 if testing.Short() && testenv.Builder() == "" {
2075 t.Skipf("skipping in -short mode on non-builder")
2078 platform := fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)
2080 case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/riscv64", "linux/s390x",
2081 "android/amd64", "android/arm", "android/arm64", "android/386",
2083 "windows/386", "windows/amd64", "windows/arm":
2084 case "darwin/amd64":
2086 t.Skipf("skipping test because buildmode=pie is not supported on %s", platform)
2088 t.Run("non-cgo", func(t *testing.T) {
2089 testBuildmodePIE(t, false, true)
2092 switch runtime.GOOS {
2093 case "darwin", "freebsd", "linux", "windows":
2094 t.Run("cgo", func(t *testing.T) {
2095 testBuildmodePIE(t, true, true)
2101 func TestWindowsDefaultBuildmodIsPIE(t *testing.T) {
2102 if testing.Short() && testenv.Builder() == "" {
2103 t.Skipf("skipping in -short mode on non-builder")
2106 if runtime.GOOS != "windows" {
2107 t.Skip("skipping windows only test")
2110 t.Run("non-cgo", func(t *testing.T) {
2111 testBuildmodePIE(t, false, false)
2114 t.Run("cgo", func(t *testing.T) {
2115 testBuildmodePIE(t, true, false)
2120 func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) {
2129 tg.tempFile("main.go", fmt.Sprintf(`package main;%s func main() { print("hello") }`, s))
2130 src := tg.path("main.go")
2131 obj := tg.path("main.exe")
2132 args := []string{"build"}
2133 if setBuildmodeToPIE {
2134 args = append(args, "-buildmode=pie")
2136 args = append(args, "-o", obj, src)
2139 switch runtime.GOOS {
2140 case "linux", "android", "freebsd":
2141 f, err := elf.Open(obj)
2146 if f.Type != elf.ET_DYN {
2147 t.Errorf("PIE type must be ET_DYN, but %s", f.Type)
2150 f, err := macho.Open(obj)
2155 if f.Flags&macho.FlagDyldLink == 0 {
2156 t.Error("PIE must have DyldLink flag, but not")
2158 if f.Flags&macho.FlagPIE == 0 {
2159 t.Error("PIE must have PIE flag, but not")
2162 f, err := pe.Open(obj)
2167 if f.Section(".reloc") == nil {
2168 t.Error(".reloc section is not present")
2170 if (f.FileHeader.Characteristics & pe.IMAGE_FILE_RELOCS_STRIPPED) != 0 {
2171 t.Error("IMAGE_FILE_RELOCS_STRIPPED flag is set")
2174 switch oh := f.OptionalHeader.(type) {
2175 case *pe.OptionalHeader32:
2176 dc = oh.DllCharacteristics
2177 case *pe.OptionalHeader64:
2178 dc = oh.DllCharacteristics
2179 if (dc & pe.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) == 0 {
2180 t.Error("IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA flag is not set")
2183 t.Fatalf("unexpected optional header type of %T", f.OptionalHeader)
2185 if (dc & pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 {
2186 t.Error("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag is not set")
2189 // Test that only one symbol is exported (#40795).
2190 // PIE binaries don´t require .edata section but unfortunately
2191 // binutils doesn´t generate a .reloc section unless there is
2192 // at least one symbol exported.
2193 // See https://sourceware.org/bugzilla/show_bug.cgi?id=19011
2194 section := f.Section(".edata")
2196 t.Skip(".edata section is not present")
2198 // TODO: deduplicate this struct from cmd/link/internal/ld/pe.go
2199 type IMAGE_EXPORT_DIRECTORY struct {
2203 NumberOfFunctions uint32
2204 NumberOfNames uint32
2207 var e IMAGE_EXPORT_DIRECTORY
2208 if err := binary.Read(section.Open(), binary.LittleEndian, &e); err != nil {
2209 t.Fatalf("binary.Read failed: %v", err)
2212 // Only _cgo_dummy_export should be exported
2213 if e.NumberOfFunctions != 1 {
2214 t.Fatalf("got %d exported functions; want 1", e.NumberOfFunctions)
2216 if e.NumberOfNames != 1 {
2217 t.Fatalf("got %d exported names; want 1", e.NumberOfNames)
2221 panic("unreachable")
2224 out, err := exec.Command(obj).CombinedOutput()
2229 if string(out) != "hello" {
2230 t.Errorf("got %q; want %q", out, "hello")
2234 func TestUpxCompression(t *testing.T) {
2235 if runtime.GOOS != "linux" ||
2236 (runtime.GOARCH != "amd64" && runtime.GOARCH != "386") {
2237 t.Skipf("skipping upx test on %s/%s", runtime.GOOS, runtime.GOARCH)
2240 testenv.MustHaveExecPath(t, "upx")
2241 out, err := exec.Command("upx", "--version").CombinedOutput()
2243 t.Fatalf("upx --version failed: %v", err)
2246 // upx --version prints `upx <version>` in the first line of output:
2249 re := regexp.MustCompile(`([[:digit:]]+)\.([[:digit:]]+)`)
2250 upxVersion := re.FindStringSubmatch(string(out))
2251 if len(upxVersion) != 3 {
2252 t.Fatalf("bad upx version string: %s", upxVersion)
2255 major, err1 := strconv.Atoi(upxVersion[1])
2256 minor, err2 := strconv.Atoi(upxVersion[2])
2257 if err1 != nil || err2 != nil {
2258 t.Fatalf("bad upx version string: %s", upxVersion[0])
2261 // Anything below 3.94 is known not to work with go binaries
2262 if (major < 3) || (major == 3 && minor < 94) {
2263 t.Skipf("skipping because upx version %v.%v is too old", major, minor)
2270 tg.tempFile("main.go", `package main; import "fmt"; func main() { fmt.Print("hello upx") }`)
2271 src := tg.path("main.go")
2272 obj := tg.path("main")
2273 tg.run("build", "-o", obj, src)
2275 out, err = exec.Command("upx", obj).CombinedOutput()
2277 t.Logf("executing upx\n%s\n", out)
2278 t.Fatalf("upx failed with %v", err)
2281 out, err = exec.Command(obj).CombinedOutput()
2284 t.Fatalf("running compressed go binary failed with error %s", err)
2286 if string(out) != "hello upx" {
2287 t.Fatalf("bad output from compressed go binary:\ngot %q; want %q", out, "hello upx")
2291 func TestCacheListStale(t *testing.T) {
2293 if godebug.Get("gocacheverify") == "1" {
2294 t.Skip("GODEBUG gocacheverify")
2300 tg.setenv("GOCACHE", tg.path("cache"))
2301 tg.tempFile("gopath/src/p/p.go", "package p; import _ \"q\"; func F(){}\n")
2302 tg.tempFile("gopath/src/q/q.go", "package q; func F(){}\n")
2303 tg.tempFile("gopath/src/m/m.go", "package main; import _ \"q\"; func main(){}\n")
2305 tg.setenv("GOPATH", tg.path("gopath"))
2306 tg.run("install", "p", "m")
2307 tg.run("list", "-f={{.ImportPath}} {{.Stale}}", "m", "q", "p")
2308 tg.grepStdout("^m false", "m should not be stale")
2309 tg.grepStdout("^q true", "q should be stale")
2310 tg.grepStdout("^p false", "p should not be stale")
2313 func TestCacheCoverage(t *testing.T) {
2316 if godebug.Get("gocacheverify") == "1" {
2317 t.Skip("GODEBUG gocacheverify")
2323 tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
2326 tg.setenv("GOCACHE", tg.path("c1"))
2327 tg.run("test", "-cover", "-short", "strings")
2328 tg.run("test", "-cover", "-short", "math", "strings")
2331 func TestIssue22588(t *testing.T) {
2332 // Don't get confused by stderr coming from tools.
2337 if _, err := os.Stat("/usr/bin/time"); err != nil {
2341 tg.run("list", "-f={{.Stale}}", "runtime")
2342 tg.run("list", "-toolexec=/usr/bin/time", "-f={{.Stale}}", "runtime")
2343 tg.grepStdout("false", "incorrectly reported runtime as stale")
2346 func TestIssue22531(t *testing.T) {
2348 if godebug.Get("gocacheverify") == "1" {
2349 t.Skip("GODEBUG gocacheverify")
2355 tg.setenv("GOPATH", tg.tempdir)
2356 tg.setenv("GOCACHE", tg.path("cache"))
2357 tg.tempFile("src/m/main.go", "package main /* c1 */; func main() {}\n")
2358 tg.run("install", "-x", "m")
2359 tg.run("list", "-f", "{{.Stale}}", "m")
2360 tg.grepStdout("false", "reported m as stale after install")
2361 tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix))
2363 // The link action ID did not include the full main build ID,
2364 // even though the full main build ID is written into the
2365 // eventual binary. That caused the following install to
2366 // be a no-op, thinking the gofmt binary was up-to-date,
2367 // even though .Stale could see it was not.
2368 tg.tempFile("src/m/main.go", "package main /* c2 */; func main() {}\n")
2369 tg.run("install", "-x", "m")
2370 tg.run("list", "-f", "{{.Stale}}", "m")
2371 tg.grepStdout("false", "reported m as stale after reinstall")
2372 tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix))
2375 func TestIssue22596(t *testing.T) {
2377 if godebug.Get("gocacheverify") == "1" {
2378 t.Skip("GODEBUG gocacheverify")
2384 tg.setenv("GOCACHE", tg.path("cache"))
2385 tg.tempFile("gopath1/src/p/p.go", "package p; func F(){}\n")
2386 tg.tempFile("gopath2/src/p/p.go", "package p; func F(){}\n")
2388 tg.setenv("GOPATH", tg.path("gopath1"))
2389 tg.run("list", "-f={{.Target}}", "p")
2390 target1 := strings.TrimSpace(tg.getStdout())
2391 tg.run("install", "p")
2392 tg.wantNotStale("p", "", "p stale after install")
2394 tg.setenv("GOPATH", tg.path("gopath2"))
2395 tg.run("list", "-f={{.Target}}", "p")
2396 target2 := strings.TrimSpace(tg.getStdout())
2397 tg.must(os.MkdirAll(filepath.Dir(target2), 0777))
2398 tg.must(copyFile(target1, target2, 0666))
2399 tg.wantStale("p", "build ID mismatch", "p not stale after copy from gopath1")
2400 tg.run("install", "p")
2401 tg.wantNotStale("p", "", "p stale after install2")
2404 func TestTestCache(t *testing.T) {
2407 if godebug.Get("gocacheverify") == "1" {
2408 t.Skip("GODEBUG gocacheverify")
2414 tg.setenv("GOPATH", tg.tempdir)
2415 tg.setenv("GOCACHE", tg.path("cache"))
2417 // The -p=1 in the commands below just makes the -x output easier to read.
2419 t.Log("\n\nINITIAL\n\n")
2421 tg.tempFile("src/p1/p1.go", "package p1\nvar X = 1\n")
2422 tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\nvar X = 1\n")
2423 tg.tempFile("src/t/t1/t1_test.go", "package t\nimport \"testing\"\nfunc Test1(*testing.T) {}\n")
2424 tg.tempFile("src/t/t2/t2_test.go", "package t\nimport _ \"p1\"\nimport \"testing\"\nfunc Test2(*testing.T) {}\n")
2425 tg.tempFile("src/t/t3/t3_test.go", "package t\nimport \"p1\"\nimport \"testing\"\nfunc Test3(t *testing.T) {t.Log(p1.X)}\n")
2426 tg.tempFile("src/t/t4/t4_test.go", "package t\nimport \"p2\"\nimport \"testing\"\nfunc Test4(t *testing.T) {t.Log(p2.X)}")
2427 tg.run("test", "-x", "-v", "-short", "t/...")
2429 t.Log("\n\nREPEAT\n\n")
2431 tg.run("test", "-x", "-v", "-short", "t/...")
2432 tg.grepStdout(`ok \tt/t1\t\(cached\)`, "did not cache t1")
2433 tg.grepStdout(`ok \tt/t2\t\(cached\)`, "did not cache t2")
2434 tg.grepStdout(`ok \tt/t3\t\(cached\)`, "did not cache t3")
2435 tg.grepStdout(`ok \tt/t4\t\(cached\)`, "did not cache t4")
2436 tg.grepStderrNot(`[\\/](compile|gccgo) `, "incorrectly ran compiler")
2437 tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker")
2438 tg.grepStderrNot(`p[0-9]\.test`, "incorrectly ran test")
2440 t.Log("\n\nCOMMENT\n\n")
2442 // Changing the program text without affecting the compiled package
2443 // should result in the package being rebuilt but nothing more.
2444 tg.tempFile("src/p1/p1.go", "package p1\nvar X = 01\n")
2445 tg.run("test", "-p=1", "-x", "-v", "-short", "t/...")
2446 tg.grepStdout(`ok \tt/t1\t\(cached\)`, "did not cache t1")
2447 tg.grepStdout(`ok \tt/t2\t\(cached\)`, "did not cache t2")
2448 tg.grepStdout(`ok \tt/t3\t\(cached\)`, "did not cache t3")
2449 tg.grepStdout(`ok \tt/t4\t\(cached\)`, "did not cache t4")
2450 tg.grepStderrNot(`([\\/](compile|gccgo) ).*t[0-9]_test\.go`, "incorrectly ran compiler")
2451 tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker")
2452 tg.grepStderrNot(`t[0-9]\.test.*test\.short`, "incorrectly ran test")
2454 t.Log("\n\nCHANGE\n\n")
2456 // Changing the actual package should have limited effects.
2457 tg.tempFile("src/p1/p1.go", "package p1\nvar X = 02\n")
2458 tg.run("test", "-p=1", "-x", "-v", "-short", "t/...")
2460 // p2 should have been rebuilt.
2461 tg.grepStderr(`([\\/]compile|gccgo).*p2.go`, "did not recompile p2")
2463 // t1 does not import anything, should not have been rebuilt.
2464 tg.grepStderrNot(`([\\/]compile|gccgo).*t1_test.go`, "incorrectly recompiled t1")
2465 tg.grepStderrNot(`([\\/]link|gccgo).*t1_test`, "incorrectly relinked t1_test")
2466 tg.grepStdout(`ok \tt/t1\t\(cached\)`, "did not cache t/t1")
2468 // t2 imports p1 and must be rebuilt and relinked,
2469 // but the change should not have any effect on the test binary,
2470 // so the test should not have been rerun.
2471 tg.grepStderr(`([\\/]compile|gccgo).*t2_test.go`, "did not recompile t2")
2472 tg.grepStderr(`([\\/]link|gccgo).*t2\.test`, "did not relink t2_test")
2473 // This check does not currently work with gccgo, as garbage
2474 // collection of unused variables is not turned on by default.
2475 if runtime.Compiler != "gccgo" {
2476 tg.grepStdout(`ok \tt/t2\t\(cached\)`, "did not cache t/t2")
2479 // t3 imports p1, and changing X changes t3's test binary.
2480 tg.grepStderr(`([\\/]compile|gccgo).*t3_test.go`, "did not recompile t3")
2481 tg.grepStderr(`([\\/]link|gccgo).*t3\.test`, "did not relink t3_test")
2482 tg.grepStderr(`t3\.test.*-test.short`, "did not rerun t3_test")
2483 tg.grepStdoutNot(`ok \tt/t3\t\(cached\)`, "reported cached t3_test result")
2485 // t4 imports p2, but p2 did not change, so t4 should be relinked, not recompiled,
2487 tg.grepStderrNot(`([\\/]compile|gccgo).*t4_test.go`, "incorrectly recompiled t4")
2488 tg.grepStderr(`([\\/]link|gccgo).*t4\.test`, "did not relink t4_test")
2489 // This check does not currently work with gccgo, as garbage
2490 // collection of unused variables is not turned on by default.
2491 if runtime.Compiler != "gccgo" {
2492 tg.grepStdout(`ok \tt/t4\t\(cached\)`, "did not cache t/t4")
2496 func TestTestSkipVetAfterFailedBuild(t *testing.T) {
2501 tg.tempFile("x_test.go", `package x
2507 tg.runFail("test", tg.path("x_test.go"))
2508 tg.grepStderrNot(`vet`, "vet should be skipped after the failed build")
2511 func TestTestVetRebuild(t *testing.T) {
2517 // golang.org/issue/23701.
2518 // b_test imports b with augmented method from export_test.go.
2519 // b_test also imports a, which imports b.
2520 // Must not accidentally see un-augmented b propagate through a to b_test.
2521 tg.tempFile("src/a/a.go", `package a
2524 func (*Type) M() b.T {return 0}
2526 tg.tempFile("src/b/b.go", `package b
2528 type I interface {M() T}
2530 tg.tempFile("src/b/export_test.go", `package b
2531 func (*T) Method() *T { return nil }
2533 tg.tempFile("src/b/b_test.go", `package b_test
2539 func TestBroken(t *testing.T) {
2546 tg.setenv("GOPATH", tg.path("."))
2551 func TestInstallDeps(t *testing.T) {
2557 tg.setenv("GOPATH", tg.tempdir)
2559 tg.tempFile("src/p1/p1.go", "package p1\nvar X = 1\n")
2560 tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\n")
2561 tg.tempFile("src/main1/main.go", "package main\nimport _ \"p2\"\nfunc main() {}\n")
2563 tg.run("list", "-f={{.Target}}", "p1")
2564 p1 := strings.TrimSpace(tg.getStdout())
2565 tg.run("list", "-f={{.Target}}", "p2")
2566 p2 := strings.TrimSpace(tg.getStdout())
2567 tg.run("list", "-f={{.Target}}", "main1")
2568 main1 := strings.TrimSpace(tg.getStdout())
2570 tg.run("install", "main1")
2576 tg.run("install", "p2")
2580 // don't let install -i overwrite runtime
2581 tg.wantNotStale("runtime", "", "must be non-stale before install -i")
2583 tg.run("install", "-i", "main1")
2585 tg.must(os.Remove(p1))
2587 tg.run("install", "-i", "p2")
2592 func TestImportPath(t *testing.T) {
2598 tg.tempFile("src/a/a.go", `
2612 tg.tempFile("src/a/a_test.go", `
2620 func TestV(t *testing.T) {
2626 tg.tempFile("src/a/p-1.0/p.go", `
2634 tg.setenv("GOPATH", tg.path("."))
2635 tg.run("build", "-o", tg.path("a.exe"), "a")
2639 func TestBadCommandLines(t *testing.T) {
2644 tg.tempFile("src/x/x.go", "package x\n")
2645 tg.setenv("GOPATH", tg.path("."))
2647 tg.run("build", "x")
2649 tg.tempFile("src/x/@y.go", "package x\n")
2650 tg.runFail("build", "x")
2651 tg.grepStderr("invalid input file name \"@y.go\"", "did not reject @y.go")
2652 tg.must(os.Remove(tg.path("src/x/@y.go")))
2654 tg.tempFile("src/x/-y.go", "package x\n")
2655 tg.runFail("build", "x")
2656 tg.grepStderr("invalid input file name \"-y.go\"", "did not reject -y.go")
2657 tg.must(os.Remove(tg.path("src/x/-y.go")))
2659 if runtime.Compiler == "gccgo" {
2660 tg.runFail("build", "-gccgoflags=all=@x", "x")
2662 tg.runFail("build", "-gcflags=all=@x", "x")
2664 tg.grepStderr("invalid command-line argument @x in command", "did not reject @x during exec")
2666 tg.tempFile("src/@x/x.go", "package x\n")
2667 tg.setenv("GOPATH", tg.path("."))
2668 tg.runFail("build", "@x")
2669 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")
2671 tg.tempFile("src/@x/y/y.go", "package y\n")
2672 tg.setenv("GOPATH", tg.path("."))
2673 tg.runFail("build", "@x/y")
2674 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")
2676 tg.tempFile("src/-x/x.go", "package x\n")
2677 tg.setenv("GOPATH", tg.path("."))
2678 tg.runFail("build", "--", "-x")
2679 tg.grepStderr("invalid import path \"-x\"", "did not reject -x import path")
2681 tg.tempFile("src/-x/y/y.go", "package y\n")
2682 tg.setenv("GOPATH", tg.path("."))
2683 tg.runFail("build", "--", "-x/y")
2684 tg.grepStderr("invalid import path \"-x/y\"", "did not reject -x/y import path")
2687 func TestTwoPkgConfigs(t *testing.T) {
2691 if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
2692 t.Skipf("no shell scripts on %s", runtime.GOOS)
2698 tg.tempFile("src/x/a.go", `package x
2699 // #cgo pkg-config: --static a
2702 tg.tempFile("src/x/b.go", `package x
2703 // #cgo pkg-config: --static a
2706 tg.tempFile("pkg-config.sh", `#!/bin/sh
2707 echo $* >>`+tg.path("pkg-config.out"))
2708 tg.must(os.Chmod(tg.path("pkg-config.sh"), 0755))
2709 tg.setenv("GOPATH", tg.path("."))
2710 tg.setenv("PKG_CONFIG", tg.path("pkg-config.sh"))
2711 tg.run("build", "x")
2712 out, err := os.ReadFile(tg.path("pkg-config.out"))
2714 out = bytes.TrimSpace(out)
2715 want := "--cflags --static --static -- a a\n--libs --static --static -- a a"
2716 if !bytes.Equal(out, []byte(want)) {
2717 t.Errorf("got %q want %q", out, want)
2721 func TestCgoCache(t *testing.T) {
2730 tg.tempFile("src/x/a.go", `package main
2737 func main() { fmt.Println(C.val) }
2739 tg.setenv("GOPATH", tg.path("."))
2740 exe := tg.path("x.exe")
2741 tg.run("build", "-o", exe, "x")
2742 tg.setenv("CGO_LDFLAGS", "-lnosuchlibraryexists")
2743 tg.runFail("build", "-o", exe, "x")
2744 tg.grepStderr(`nosuchlibraryexists`, "did not run linker with changed CGO_LDFLAGS")
2748 func TestFilepathUnderCwdFormat(t *testing.T) {
2752 tg.run("test", "-x", "-cover", "log")
2753 tg.grepStderrNot(`\.log\.cover\.go`, "-x output should contain correctly formatted filepath under cwd")
2757 func TestDontReportRemoveOfEmptyDir(t *testing.T) {
2761 tg.tempFile("src/a/a.go", `package a`)
2762 tg.setenv("GOPATH", tg.path("."))
2763 tg.run("install", "-x", "a")
2764 tg.run("install", "-x", "a")
2765 // The second install should have printed only a WORK= line,
2767 if bytes.Count(tg.stdout.Bytes(), []byte{'\n'})+bytes.Count(tg.stderr.Bytes(), []byte{'\n'}) > 1 {
2768 t.Error("unnecessary output when installing installed package")
2773 func TestLinkerTmpDirIsDeleted(t *testing.T) {
2774 skipIfGccgo(t, "gccgo does not use cmd/link")
2776 t.Skip("skipping because cgo not enabled")
2783 tg.tempFile("a.go", `package main; import "C"; func main() {}`)
2784 tg.run("build", "-ldflags", "-v", "-o", os.DevNull, tg.path("a.go"))
2785 // Find line that has "host link:" in linker output.
2786 stderr := tg.getStderr()
2787 var hostLinkLine string
2788 for _, line := range strings.Split(stderr, "\n") {
2789 if !strings.Contains(line, "host link:") {
2795 if hostLinkLine == "" {
2796 t.Fatal(`fail to find with "host link:" string in linker output`)
2798 // Find parameter, like "/tmp/go-link-408556474/go.o" inside of
2799 // "host link:" line, and extract temp directory /tmp/go-link-408556474
2801 tmpdir := hostLinkLine
2802 i := strings.Index(tmpdir, `go.o"`)
2804 t.Fatalf(`fail to find "go.o" in "host link:" line %q`, hostLinkLine)
2806 tmpdir = tmpdir[:i-1]
2807 i = strings.LastIndex(tmpdir, `"`)
2809 t.Fatalf(`fail to find " in "host link:" line %q`, hostLinkLine)
2811 tmpdir = tmpdir[i+1:]
2812 // Verify that temp directory has been removed.
2813 _, err := os.Stat(tmpdir)
2815 t.Fatalf("temp directory %q has not been removed", tmpdir)
2817 if !os.IsNotExist(err) {
2818 t.Fatalf("Stat(%q) returns unexpected error: %v", tmpdir, err)
2823 func TestCoverpkgTestOnly(t *testing.T) {
2824 skipIfGccgo(t, "gccgo has no cover tool")
2829 tg.tempFile("src/a/a.go", `package a
2833 tg.tempFile("src/atest/a_test.go", `
2835 import ( "a"; "testing" )
2836 func TestF(t *testing.T) { a.F(2) }
2838 tg.setenv("GOPATH", tg.path("."))
2839 tg.run("test", "-coverpkg=a", "atest")
2840 tg.grepStderrNot("no packages being tested depend on matches", "bad match message")
2841 tg.grepStdout("coverage: 100", "no coverage")
2844 // Regression test for golang.org/issue/34499: version command should not crash
2845 // when executed in a deleted directory on Linux.
2846 func TestExecInDeletedDir(t *testing.T) {
2847 switch runtime.GOOS {
2848 case "windows", "plan9",
2849 "aix", // Fails with "device busy".
2850 "solaris", "illumos": // Fails with "invalid argument".
2851 t.Skipf("%v does not support removing the current working directory", runtime.GOOS)
2856 wd, err := os.Getwd()
2859 tg.check(os.Chdir(tg.tempdir))
2860 defer func() { tg.check(os.Chdir(wd)) }()
2862 tg.check(os.Remove(tg.tempdir))
2864 // `go version` should not fail
2868 // A missing C compiler should not force the net package to be stale.
2870 func TestMissingCC(t *testing.T) {
2872 t.Skip("test is only meaningful on systems with cgo")
2874 cc := os.Getenv("CC")
2878 if filepath.IsAbs(cc) {
2879 t.Skipf(`"CC" (%s) is an absolute path`, cc)
2881 _, err := exec.LookPath(cc)
2883 t.Skipf(`"CC" (%s) not on PATH`, cc)
2888 netStale, _ := tg.isStale("net")
2890 t.Skip(`skipping test because "net" package is currently stale`)
2893 tg.setenv("PATH", "") // No C compiler on PATH.
2894 netStale, _ = tg.isStale("net")
2896 t.Error(`clearing "PATH" causes "net" to be stale`)