]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/go/go_test.go
cmd/go: don't install most GOROOT .a files in pkg
[gostls13.git] / src / cmd / go / go_test.go
1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package main_test
6
7 import (
8         "bytes"
9         "debug/elf"
10         "debug/macho"
11         "debug/pe"
12         "encoding/binary"
13         "flag"
14         "fmt"
15         "go/format"
16         "internal/godebug"
17         "internal/platform"
18         "internal/testenv"
19         "io"
20         "io/fs"
21         "log"
22         "os"
23         "os/exec"
24         "path/filepath"
25         "regexp"
26         "runtime"
27         "strconv"
28         "strings"
29         "testing"
30         "time"
31
32         "cmd/go/internal/cache"
33         "cmd/go/internal/cfg"
34         "cmd/go/internal/robustio"
35         "cmd/go/internal/search"
36         "cmd/go/internal/vcs"
37         "cmd/go/internal/vcweb/vcstest"
38         "cmd/go/internal/web"
39         "cmd/go/internal/work"
40         "cmd/internal/sys"
41
42         cmdgo "cmd/go"
43 )
44
45 func init() {
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")
51 }
52
53 var (
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
58 )
59
60 var (
61         goHostOS, goHostArch string
62         cgoEnabled           string // raw value from 'go env CGO_ENABLED'
63 )
64
65 var exeSuffix string = func() string {
66         if runtime.GOOS == "windows" {
67                 return ".exe"
68         }
69         return ""
70 }()
71
72 func tooSlow(t *testing.T) {
73         if testing.Short() {
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") {
76                         return
77                 }
78                 t.Helper()
79                 t.Skip("skipping test in -short mode")
80         }
81 }
82
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
85 // (temp) directory.
86 var testGOROOT string
87
88 // testGOROOT_FINAL is the GOROOT_FINAL with which the test binary is assumed to
89 // have been built.
90 var testGOROOT_FINAL = os.Getenv("GOROOT_FINAL")
91
92 var testGOCACHE string
93
94 var testGo string
95 var testTmpDir string
96 var testBin string
97
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)
107
108                 if v := os.Getenv("TESTGO_VERSION"); v != "" {
109                         work.RuntimeVersion = v
110                 }
111
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 {
116                                 if cfg.BuildN {
117                                         return nil
118                                 }
119
120                                 rel := search.InDir(a.Target, testGOROOT)
121                                 if rel == "" {
122                                         return nil
123                                 }
124
125                                 callerPos := ""
126                                 if _, file, line, ok := runtime.Caller(1); ok {
127                                         if shortFile := search.InDir(file, filepath.Join(testGOROOT, "src")); shortFile != "" {
128                                                 file = shortFile
129                                         }
130                                         callerPos = fmt.Sprintf("%s:%d: ", file, line)
131                                 }
132                                 return fmt.Errorf("%stestgo must not write to GOROOT (installing to %s)", callerPos, filepath.Join("GOROOT", rel))
133                         }
134                 }
135
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"))
141                         if err != nil {
142                                 fmt.Fprintf(os.Stderr, "loading certificates from $TESTGO_VCSTEST_CERT: %v", err)
143                         }
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})
149                         }
150                         web.EnableTestHooks(interceptors)
151                 }
152
153                 cmdgo.Main()
154                 os.Exit(0)
155         }
156         os.Setenv("CMDGO_TEST_RUN_MAIN", "true")
157
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")
163                 fmt.Printf("SKIP\n")
164                 return
165         }
166
167         flag.Parse()
168
169         if *proxyAddr != "" {
170                 StartProxy()
171                 select {}
172         }
173
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-")
177         if err != nil {
178                 log.Fatal(err)
179         }
180         if !*testWork {
181                 defer removeAll(topTmpdir)
182         } else {
183                 fmt.Fprintf(os.Stderr, "TESTWORK: preserving top level tempdir %s\n", topTmpdir)
184         }
185         os.Setenv(tempEnvName(), topTmpdir)
186
187         dir, err := os.MkdirTemp(topTmpdir, "tmpdir")
188         if err != nil {
189                 log.Fatal(err)
190         }
191         testTmpDir = dir
192         if !*testWork {
193                 defer removeAll(testTmpDir)
194         }
195
196         testGOCACHE = cache.DefaultDir()
197         if testenv.HasGoBuild() {
198                 testBin = filepath.Join(testTmpDir, "testbin")
199                 if err := os.Mkdir(testBin, 0777); err != nil {
200                         log.Fatal(err)
201                 }
202                 testGo = filepath.Join(testBin, "go"+exeSuffix)
203                 gotool, err := testenv.GoTool()
204                 if err != nil {
205                         fmt.Fprintln(os.Stderr, "locating go tool: ", err)
206                         os.Exit(2)
207                 }
208
209                 goEnv := func(name string) string {
210                         out, err := exec.Command(gotool, "env", name).CombinedOutput()
211                         if err != nil {
212                                 fmt.Fprintf(os.Stderr, "go env %s: %v\n%s", name, err, out)
213                                 os.Exit(2)
214                         }
215                         return strings.TrimSpace(string(out))
216                 }
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)
224
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)
240
241                 cgoEnabled = goEnv("CGO_ENABLED")
242                 canCgo, err = strconv.ParseBool(cgoEnabled)
243                 if err != nil {
244                         fmt.Fprintf(os.Stderr, "can't parse go env CGO_ENABLED output: %q\n", strings.TrimSpace(cgoEnabled))
245                         os.Exit(2)
246                 }
247
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()
251                 if err != nil {
252                         log.Fatal(err)
253                 }
254                 if err := os.Symlink(testExe, testGo); err != nil {
255                         // Otherwise, copy the bytes.
256                         src, err := os.Open(testExe)
257                         if err != nil {
258                                 log.Fatal(err)
259                         }
260                         defer src.Close()
261
262                         dst, err := os.OpenFile(testGo, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o777)
263                         if err != nil {
264                                 log.Fatal(err)
265                         }
266
267                         _, err = io.Copy(dst, src)
268                         if closeErr := dst.Close(); err == nil {
269                                 err = closeErr
270                         }
271                         if err != nil {
272                                 log.Fatal(err)
273                         }
274                 }
275
276                 out, err := exec.Command(gotool, "env", "GOCACHE").CombinedOutput()
277                 if err != nil {
278                         fmt.Fprintf(os.Stderr, "could not find testing GOCACHE: %v\n%s", err, out)
279                         os.Exit(2)
280                 }
281                 testGOCACHE = strings.TrimSpace(string(out))
282
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" {
290                         canRace = false
291                 }
292         }
293
294         // Don't let these environment variables confuse the test.
295         os.Setenv("GOENV", "off")
296         os.Unsetenv("GOFLAGS")
297         os.Unsetenv("GOBIN")
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
307         }
308
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")
315         }
316
317         r := m.Run()
318         if !*testWork {
319                 removeAll(testTmpDir) // os.Exit won't run defer
320         }
321
322         if !*testWork {
323                 // There shouldn't be anything left in topTmpdir.
324                 dirf, err := os.Open(topTmpdir)
325                 if err != nil {
326                         log.Fatal(err)
327                 }
328                 names, err := dirf.Readdirnames(0)
329                 if err != nil {
330                         log.Fatal(err)
331                 }
332                 if len(names) > 0 {
333                         log.Fatalf("unexpected files left in tmpdir: %v", names)
334                 }
335
336                 removeAll(topTmpdir)
337         }
338
339         os.Exit(r)
340 }
341
342 func isAlpineLinux() bool {
343         if runtime.GOOS != "linux" {
344                 return false
345         }
346         fi, err := os.Lstat("/etc/alpine-release")
347         return err == nil && fi.Mode().IsRegular()
348 }
349
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
352 // different.
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
355
356 // Manage a single run of the testgo binary.
357 type testgoData struct {
358         t              *testing.T
359         temps          []string
360         env            []string
361         tempdir        string
362         ran            bool
363         inParallel     bool
364         stdout, stderr bytes.Buffer
365         execDir        string // dir for tg.run
366 }
367
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)
372         }
373 }
374
375 // testgo sets up for a test that runs testgo.
376 func testgo(t *testing.T) *testgoData {
377         t.Helper()
378         testenv.MustHaveGoBuild(t)
379         testenv.SkipIfShortAndSlow(t)
380
381         return &testgoData{t: t}
382 }
383
384 // must gives a fatal error if err is not nil.
385 func (tg *testgoData) must(err error) {
386         tg.t.Helper()
387         if err != nil {
388                 tg.t.Fatal(err)
389         }
390 }
391
392 // check gives a test non-fatal error if err is not nil.
393 func (tg *testgoData) check(err error) {
394         tg.t.Helper()
395         if err != nil {
396                 tg.t.Error(err)
397         }
398 }
399
400 // parallel runs the test in parallel by calling t.Parallel.
401 func (tg *testgoData) parallel() {
402         tg.t.Helper()
403         if tg.ran {
404                 tg.t.Fatal("internal testsuite error: call to parallel after run")
405         }
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)
411                         }
412                 }
413         }
414         tg.inParallel = true
415         tg.t.Parallel()
416 }
417
418 // pwd returns the current directory.
419 func (tg *testgoData) pwd() string {
420         tg.t.Helper()
421         wd, err := os.Getwd()
422         if err != nil {
423                 tg.t.Fatalf("could not get working directory: %v", err)
424         }
425         return wd
426 }
427
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
430 // mtime.
431 func (tg *testgoData) sleep() {
432         time.Sleep(mtimeTick)
433 }
434
435 // setenv sets an environment variable to use when running the test go
436 // command.
437 func (tg *testgoData) setenv(name, val string) {
438         tg.t.Helper()
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)
441         }
442         tg.unsetenv(name)
443         tg.env = append(tg.env, name+"="+val)
444 }
445
446 // unsetenv removes an environment variable.
447 func (tg *testgoData) unsetenv(name string) {
448         if tg.env == nil {
449                 tg.env = append([]string(nil), os.Environ()...)
450                 tg.env = append(tg.env, "GO111MODULE=off")
451         }
452         for i, v := range tg.env {
453                 if strings.HasPrefix(v, name+"=") {
454                         tg.env = append(tg.env[:i], tg.env[i+1:]...)
455                         break
456                 }
457         }
458 }
459
460 func (tg *testgoData) goTool() string {
461         return testGo
462 }
463
464 // doRun runs the test go command, recording stdout and stderr and
465 // returning exit status.
466 func (tg *testgoData) doRun(args []string) error {
467         tg.t.Helper()
468         if tg.inParallel {
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")
472                         }
473                 }
474         }
475
476         hasGoroot := false
477         for _, v := range tg.env {
478                 if strings.HasPrefix(v, "GOROOT=") {
479                         hasGoroot = true
480                         break
481                 }
482         }
483         prog := tg.goTool()
484         if !hasGoroot {
485                 tg.setenv("GOROOT", testGOROOT)
486         }
487
488         tg.t.Logf("running testgo %v", args)
489         cmd := exec.Command(prog, args...)
490         tg.stdout.Reset()
491         tg.stderr.Reset()
492         cmd.Dir = tg.execDir
493         cmd.Stdout = &tg.stdout
494         cmd.Stderr = &tg.stderr
495         cmd.Env = tg.env
496         status := cmd.Run()
497         if tg.stdout.Len() > 0 {
498                 tg.t.Log("standard output:")
499                 tg.t.Log(tg.stdout.String())
500         }
501         if tg.stderr.Len() > 0 {
502                 tg.t.Log("standard error:")
503                 tg.t.Log(tg.stderr.String())
504         }
505         tg.ran = true
506         return status
507 }
508
509 // run runs the test go command, and expects it to succeed.
510 func (tg *testgoData) run(args ...string) {
511         tg.t.Helper()
512         if status := tg.doRun(args); status != nil {
513                 wd, _ := os.Getwd()
514                 tg.t.Logf("go %v failed unexpectedly in %s: %v", args, wd, status)
515                 tg.t.FailNow()
516         }
517 }
518
519 // runFail runs the test go command, and expects it to fail.
520 func (tg *testgoData) runFail(args ...string) {
521         tg.t.Helper()
522         if status := tg.doRun(args); status == nil {
523                 tg.t.Fatal("testgo succeeded unexpectedly")
524         } else {
525                 tg.t.Log("testgo failed as expected:", status)
526         }
527 }
528
529 // runGit runs a git command, and expects it to succeed.
530 func (tg *testgoData) runGit(dir string, args ...string) {
531         tg.t.Helper()
532         cmd := exec.Command("git", args...)
533         tg.stdout.Reset()
534         tg.stderr.Reset()
535         cmd.Stdout = &tg.stdout
536         cmd.Stderr = &tg.stderr
537         cmd.Dir = dir
538         cmd.Env = tg.env
539         status := cmd.Run()
540         if tg.stdout.Len() > 0 {
541                 tg.t.Log("git standard output:")
542                 tg.t.Log(tg.stdout.String())
543         }
544         if tg.stderr.Len() > 0 {
545                 tg.t.Log("git standard error:")
546                 tg.t.Log(tg.stderr.String())
547         }
548         if status != nil {
549                 tg.t.Logf("git %v failed unexpectedly: %v", args, status)
550                 tg.t.FailNow()
551         }
552 }
553
554 // getStdout returns standard output of the testgo run as a string.
555 func (tg *testgoData) getStdout() string {
556         tg.t.Helper()
557         if !tg.ran {
558                 tg.t.Fatal("internal testsuite error: stdout called before run")
559         }
560         return tg.stdout.String()
561 }
562
563 // getStderr returns standard error of the testgo run as a string.
564 func (tg *testgoData) getStderr() string {
565         tg.t.Helper()
566         if !tg.ran {
567                 tg.t.Fatal("internal testsuite error: stdout called before run")
568         }
569         return tg.stderr.String()
570 }
571
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 {
576         tg.t.Helper()
577         if !tg.ran {
578                 tg.t.Fatal("internal testsuite error: grep called before run")
579         }
580         re := regexp.MustCompile(match)
581         for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) {
582                 if re.Match(ln) {
583                         return true
584                 }
585         }
586         return false
587 }
588
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
592 // failure.
593 func (tg *testgoData) doGrep(match string, b *bytes.Buffer, name, msg string) {
594         tg.t.Helper()
595         if !tg.doGrepMatch(match, b) {
596                 tg.t.Log(msg)
597                 tg.t.Logf("pattern %v not found in standard %s", match, name)
598                 tg.t.FailNow()
599         }
600 }
601
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) {
605         tg.t.Helper()
606         tg.doGrep(match, &tg.stdout, "output", msg)
607 }
608
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) {
612         tg.t.Helper()
613         tg.doGrep(match, &tg.stderr, "error", msg)
614 }
615
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) {
619         tg.t.Helper()
620         if !tg.doGrepMatch(match, &tg.stdout) && !tg.doGrepMatch(match, &tg.stderr) {
621                 tg.t.Log(msg)
622                 tg.t.Logf("pattern %v not found in standard output or standard error", match)
623                 tg.t.FailNow()
624         }
625 }
626
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) {
630         tg.t.Helper()
631         if tg.doGrepMatch(match, b) {
632                 tg.t.Log(msg)
633                 tg.t.Logf("pattern %v found unexpectedly in standard %s", match, name)
634                 tg.t.FailNow()
635         }
636 }
637
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) {
641         tg.t.Helper()
642         tg.doGrepNot(match, &tg.stdout, "output", msg)
643 }
644
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) {
648         tg.t.Helper()
649         tg.doGrepNot(match, &tg.stderr, "error", msg)
650 }
651
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
654 // found.
655 func (tg *testgoData) grepBothNot(match, msg string) {
656         tg.t.Helper()
657         if tg.doGrepMatch(match, &tg.stdout) || tg.doGrepMatch(match, &tg.stderr) {
658                 tg.t.Log(msg)
659                 tg.t.Fatalf("pattern %v found unexpectedly in standard output or standard error", match)
660         }
661 }
662
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 {
665         tg.t.Helper()
666         if !tg.ran {
667                 tg.t.Fatal("internal testsuite error: doGrepCount called before run")
668         }
669         re := regexp.MustCompile(match)
670         c := 0
671         for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) {
672                 if re.Match(ln) {
673                         c++
674                 }
675         }
676         return c
677 }
678
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 {
682         tg.t.Helper()
683         return tg.doGrepCount(match, &tg.stdout) + tg.doGrepCount(match, &tg.stderr)
684 }
685
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) {
691         tg.t.Helper()
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)
694         }
695         tg.must(robustio.RemoveAll(path))
696         tg.temps = append(tg.temps, path)
697 }
698
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() {
702         tg.t.Helper()
703         if tg.tempdir == "" {
704                 var err error
705                 tg.tempdir, err = os.MkdirTemp("", "gotest")
706                 tg.must(err)
707         }
708 }
709
710 // tempFile adds a temporary file for a run of testgo.
711 func (tg *testgoData) tempFile(path, contents string) {
712         tg.t.Helper()
713         tg.makeTempdir()
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)
718                 if err == nil {
719                         bytes = formatted
720                 }
721         }
722         tg.must(os.WriteFile(filepath.Join(tg.tempdir, path), bytes, 0644))
723 }
724
725 // tempDir adds a temporary directory for a run of testgo.
726 func (tg *testgoData) tempDir(path string) {
727         tg.t.Helper()
728         tg.makeTempdir()
729         if err := os.MkdirAll(filepath.Join(tg.tempdir, path), 0755); err != nil && !os.IsExist(err) {
730                 tg.t.Fatal(err)
731         }
732 }
733
734 // path returns the absolute pathname to file with the temporary
735 // directory.
736 func (tg *testgoData) path(name string) string {
737         tg.t.Helper()
738         if tg.tempdir == "" {
739                 tg.t.Fatalf("internal testsuite error: path(%q) with no tempdir", name)
740         }
741         if name == "." {
742                 return tg.tempdir
743         }
744         return filepath.Join(tg.tempdir, name)
745 }
746
747 // mustExist fails if path does not exist.
748 func (tg *testgoData) mustExist(path string) {
749         tg.t.Helper()
750         if _, err := os.Stat(path); err != nil {
751                 if os.IsNotExist(err) {
752                         tg.t.Fatalf("%s does not exist but should", path)
753                 }
754                 tg.t.Fatalf("%s stat failed: %v", path, err)
755         }
756 }
757
758 // mustNotExist fails if path exists.
759 func (tg *testgoData) mustNotExist(path string) {
760         tg.t.Helper()
761         if _, err := os.Stat(path); err == nil || !os.IsNotExist(err) {
762                 tg.t.Fatalf("%s exists but should not (%v)", path, err)
763         }
764 }
765
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)
771         if err != nil {
772                 tg.t.Fatal(err)
773         }
774         if f.Size() == 0 {
775                 tg.t.Fatalf("expected %s to have data, but is empty", filePath)
776         }
777 }
778
779 // wantExecutable fails with msg if path is not executable.
780 func (tg *testgoData) wantExecutable(path, msg string) {
781         tg.t.Helper()
782         if st, err := os.Stat(path); err != nil {
783                 if !os.IsNotExist(err) {
784                         tg.t.Log(err)
785                 }
786                 tg.t.Fatal(msg)
787         } else {
788                 if runtime.GOOS != "windows" && st.Mode()&0111 == 0 {
789                         tg.t.Fatalf("binary %s exists but is not executable", path)
790                 }
791         }
792 }
793
794 // isStale reports whether pkg is stale, and why
795 func (tg *testgoData) isStale(pkg string) (bool, string) {
796         tg.t.Helper()
797         tg.run("list", "-f", "{{.Stale}}:{{.StaleReason}}", pkg)
798         v := strings.TrimSpace(tg.getStdout())
799         f := strings.SplitN(v, ":", 2)
800         if len(f) == 2 {
801                 switch f[0] {
802                 case "true":
803                         return true, f[1]
804                 case "false":
805                         return false, f[1]
806                 }
807         }
808         tg.t.Fatalf("unexpected output checking staleness of package %v: %v", pkg, v)
809         panic("unreachable")
810 }
811
812 // wantStale fails with msg if pkg is not stale.
813 func (tg *testgoData) wantStale(pkg, reason, msg string) {
814         tg.t.Helper()
815         stale, why := tg.isStale(pkg)
816         if !stale {
817                 tg.t.Fatal(msg)
818         }
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)
825         }
826 }
827
828 // wantNotStale fails with msg if pkg is stale.
829 func (tg *testgoData) wantNotStale(pkg, reason, msg string) {
830         tg.t.Helper()
831         stale, why := tg.isStale(pkg)
832         if stale {
833                 tg.t.Fatal(msg)
834         }
835         if reason == "" && why != "" || !strings.Contains(why, reason) {
836                 tg.t.Errorf("wrong reason for Stale=false: %q, want %q", why, reason)
837         }
838 }
839
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, "")
844
845 // cleanup cleans up a test that runs testgo.
846 func (tg *testgoData) cleanup() {
847         tg.t.Helper()
848         if *testWork {
849                 if tg.tempdir != "" {
850                         tg.t.Logf("TESTWORK=%s\n", tg.path("."))
851                 }
852                 return
853         }
854         for _, path := range tg.temps {
855                 tg.check(removeAll(path))
856         }
857         if tg.tempdir != "" {
858                 tg.check(removeAll(tg.tempdir))
859         }
860 }
861
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() {
869                         os.Chmod(path, 0777)
870                 }
871                 return nil
872         })
873         return robustio.RemoveAll(dir)
874 }
875
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() {
879         tg.t.Helper()
880         wd, err := os.Getwd()
881         if err != nil {
882                 tg.t.Fatal(err)
883         }
884         fail := filepath.Join(wd, "testdata/failssh")
885         tg.setenv("PATH", fmt.Sprintf("%v%c%v", fail, filepath.ListSeparator, os.Getenv("PATH")))
886 }
887
888 func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
889         if testing.Short() {
890                 t.Skip("skipping lengthy test in short mode")
891         }
892
893         tg := testgo(t)
894         defer tg.cleanup()
895         tg.parallel()
896
897         // Copy the runtime packages into a temporary GOROOT
898         // so that we can change files.
899         for _, copydir := range []string{
900                 "src/runtime",
901                 "src/internal/abi",
902                 "src/internal/bytealg",
903                 "src/internal/coverage/rtcov",
904                 "src/internal/cpu",
905                 "src/internal/goarch",
906                 "src/internal/goexperiment",
907                 "src/internal/goos",
908                 "src/internal/coverage/rtcov",
909                 "src/math/bits",
910                 "src/unsafe",
911                 filepath.Join("pkg", runtime.GOOS+"_"+runtime.GOARCH),
912                 filepath.Join("pkg/tool", goHostOS+"_"+goHostArch),
913                 "pkg/include",
914         } {
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 {
919                                 if err != nil {
920                                         return err
921                                 }
922                                 if info.IsDir() {
923                                         return nil
924                                 }
925                                 srcrel, err := filepath.Rel(srcdir, path)
926                                 if err != nil {
927                                         return err
928                                 }
929                                 dest := filepath.Join("goroot", copydir, srcrel)
930                                 data, err := os.ReadFile(path)
931                                 if err != nil {
932                                         return err
933                                 }
934                                 tg.tempFile(dest, string(data))
935                                 if strings.Contains(copydir, filepath.Join("pkg", "tool")) {
936                                         os.Chmod(tg.path(dest), 0777)
937                                 }
938                                 return nil
939                         })
940                 if err != nil {
941                         t.Fatal(err)
942                 }
943         }
944         tg.setenv("GOROOT", tg.path("goroot"))
945
946         addVar := func(name string, idx int) (restore func()) {
947                 data, err := os.ReadFile(name)
948                 if err != nil {
949                         t.Fatal(err)
950                 }
951                 old := data
952                 data = append(data, fmt.Sprintf("var DummyUnusedVar%d bool\n", idx)...)
953                 if err := os.WriteFile(name, append(data, '\n'), 0666); err != nil {
954                         t.Fatal(err)
955                 }
956                 tg.sleep()
957                 return func() {
958                         if err := os.WriteFile(name, old, 0666); err != nil {
959                                 t.Fatal(err)
960                         }
961                 }
962         }
963
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")
970
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")
975         tg.sleep()
976         restore := addVar(sys, 0)
977         restore()
978         tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after updating mtime of runtime/internal/sys/sys.go")
979
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)
984         defer restore()
985         tg.wantStale("p1", "stale dependency: runtime/internal", "./testgo list claims p1 is NOT stale, incorrectly, after changing sys.go")
986         restore()
987         tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after changing back to old release")
988         addVar(sys, 2)
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")
992
993         // Restore to "old" release.
994         restore()
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")
998 }
999
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")
1004
1005         tg := testgo(t)
1006         defer tg.cleanup()
1007         tg.parallel()
1008         tg.tempDir("src")
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)
1015 }
1016
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")
1021
1022         tg := testgo(t)
1023         defer tg.cleanup()
1024         tg.parallel()
1025         tg.tempDir("src")
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")
1031
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")
1040         }
1041 }
1042
1043 func TestGetGitDefaultBranch(t *testing.T) {
1044         testenv.MustHaveExternalNetwork(t)
1045         testenv.MustHaveExecPath(t, "git")
1046
1047         tg := testgo(t)
1048         defer tg.cleanup()
1049         tg.parallel()
1050         tg.tempDir("src")
1051         tg.setenv("GOPATH", tg.path("."))
1052
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"
1057
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")
1062
1063         tg.run("get", "-d", "-u", importPath)
1064         tg.runGit(repoDir, "branch", "--contains", "HEAD")
1065         tg.grepStdout(`\* another-branch`, "not on correct default branch")
1066 }
1067
1068 func TestPackageMainTestCompilerFlags(t *testing.T) {
1069         tg := testgo(t)
1070         defer tg.cleanup()
1071         tg.parallel()
1072         tg.makeTempdir()
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")
1079 }
1080
1081 // Issue 4104.
1082 func TestGoTestWithPackageListedMultipleTimes(t *testing.T) {
1083         tooSlow(t)
1084         tg := testgo(t)
1085         defer tg.cleanup()
1086         tg.parallel()
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")
1090         }
1091 }
1092
1093 func TestGoListHasAConsistentOrder(t *testing.T) {
1094         tooSlow(t)
1095         tg := testgo(t)
1096         defer tg.cleanup()
1097         tg.parallel()
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")
1103         }
1104 }
1105
1106 func TestGoListStdDoesNotIncludeCommands(t *testing.T) {
1107         tooSlow(t)
1108         tg := testgo(t)
1109         defer tg.cleanup()
1110         tg.parallel()
1111         tg.run("list", "std")
1112         tg.grepStdoutNot("cmd/", "go list std shows commands")
1113 }
1114
1115 func TestGoListCmdOnlyShowsCommands(t *testing.T) {
1116         skipIfGccgo(t, "gccgo does not have GOROOT")
1117         tooSlow(t)
1118         tg := testgo(t)
1119         defer tg.cleanup()
1120         tg.parallel()
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")
1126                         break
1127                 }
1128         }
1129 }
1130
1131 func TestGoListDeps(t *testing.T) {
1132         tg := testgo(t)
1133         defer tg.cleanup()
1134         tg.parallel()
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")
1143
1144         tg.run("list", "-deps", "p1")
1145         tg.grepStdout("p1/p2/p3/p4", "-deps p1 does not mention p4")
1146
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"
1155                 }
1156                 if tg.stdout.String() != want {
1157                         t.Fatalf("list -deps math: wrong order\nhave %q\nwant %q", tg.stdout.String(), want)
1158                 }
1159         }
1160 }
1161
1162 func TestGoListTest(t *testing.T) {
1163         skipIfGccgo(t, "gccgo does not have standard packages")
1164         tg := testgo(t)
1165         defer tg.cleanup()
1166         tg.parallel()
1167         tg.makeTempdir()
1168         tg.setenv("GOCACHE", tg.tempdir)
1169
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")
1176
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")
1183
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")
1190
1191         tg.run("list", "-test", "runtime/cgo")
1192         tg.grepStdout(`^runtime/cgo$`, "missing runtime/cgo")
1193
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")
1197 }
1198
1199 func TestGoListCompiledCgo(t *testing.T) {
1200         tooSlow(t)
1201         tg := testgo(t)
1202         defer tg.cleanup()
1203         tg.parallel()
1204         tg.makeTempdir()
1205         tg.setenv("GOCACHE", tg.tempdir)
1206
1207         tg.run("list", "-f", `{{join .CgoFiles "\n"}}`, "net")
1208         if tg.stdout.String() == "" {
1209                 t.Skip("net does not use cgo")
1210         }
1211         if strings.Contains(tg.stdout.String(), tg.tempdir) {
1212                 t.Fatalf(".CgoFiles unexpectedly mentioned cache %s", tg.tempdir)
1213         }
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)
1217         }
1218         dir := ""
1219         for _, file := range strings.Split(tg.stdout.String(), "\n") {
1220                 if file == "" {
1221                         continue
1222                 }
1223                 if dir == "" {
1224                         dir = file
1225                         continue
1226                 }
1227                 if !strings.Contains(file, "/") && !strings.Contains(file, `\`) {
1228                         file = filepath.Join(dir, file)
1229                 }
1230                 if _, err := os.Stat(file); err != nil {
1231                         t.Fatalf("cannot find .CompiledGoFiles result %s: %v", file, err)
1232                 }
1233         }
1234 }
1235
1236 func TestGoListExport(t *testing.T) {
1237         skipIfGccgo(t, "gccgo does not have standard packages")
1238         tg := testgo(t)
1239         defer tg.cleanup()
1240         tg.parallel()
1241         tg.makeTempdir()
1242         tg.setenv("GOCACHE", tg.tempdir)
1243
1244         tg.run("list", "-f", "{{.Export}}", "strings")
1245         if tg.stdout.String() != "" {
1246                 t.Fatalf(".Export without -export unexpectedly set")
1247         }
1248         tg.run("list", "-export", "-f", "{{.Export}}", "strings")
1249         file := strings.TrimSpace(tg.stdout.String())
1250         if file == "" {
1251                 t.Fatalf(".Export with -export was empty")
1252         }
1253         if _, err := os.Stat(file); err != nil {
1254                 t.Fatalf("cannot find .Export result %s: %v", file, err)
1255         }
1256
1257         tg.run("list", "-export", "-f", "{{.BuildID}}", "strings")
1258         buildID := strings.TrimSpace(tg.stdout.String())
1259         if buildID == "" {
1260                 t.Fatalf(".BuildID with -export was empty")
1261         }
1262
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)
1267         }
1268 }
1269
1270 // Issue 4096. Validate the output of unsuccessful go install foo/quxx.
1271 func TestUnsuccessfulGoInstallShouldMentionMissingPackage(t *testing.T) {
1272         tg := testgo(t)
1273         defer tg.cleanup()
1274         tg.parallel()
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`)
1278         }
1279 }
1280
1281 func TestGOROOTSearchFailureReporting(t *testing.T) {
1282         tg := testgo(t)
1283         defer tg.cleanup()
1284         tg.parallel()
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)`)
1288         }
1289 }
1290
1291 func TestMultipleGOPATHEntriesReportedSeparately(t *testing.T) {
1292         tg := testgo(t)
1293         defer tg.cleanup()
1294         tg.parallel()
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`)
1300         }
1301 }
1302
1303 // Test (from $GOPATH) annotation is reported for the first GOPATH entry,
1304 func TestMentionGOPATHInFirstGOPATHEntry(t *testing.T) {
1305         tg := testgo(t)
1306         defer tg.cleanup()
1307         tg.parallel()
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)`)
1313         }
1314 }
1315
1316 // but not on the second.
1317 func TestMentionGOPATHNotOnSecondEntry(t *testing.T) {
1318         tg := testgo(t)
1319         defer tg.cleanup()
1320         tg.parallel()
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`)
1326         }
1327 }
1328
1329 func homeEnvName() string {
1330         switch runtime.GOOS {
1331         case "windows":
1332                 return "USERPROFILE"
1333         case "plan9":
1334                 return "home"
1335         default:
1336                 return "HOME"
1337         }
1338 }
1339
1340 func tempEnvName() string {
1341         switch runtime.GOOS {
1342         case "windows":
1343                 return "TMP"
1344         case "plan9":
1345                 return "TMPDIR" // actually plan 9 doesn't have one at all but this is fine
1346         default:
1347                 return "TMPDIR"
1348         }
1349 }
1350
1351 func pathEnvName() string {
1352         switch runtime.GOOS {
1353         case "plan9":
1354                 return "path"
1355         default:
1356                 return "PATH"
1357         }
1358 }
1359
1360 func TestDefaultGOPATH(t *testing.T) {
1361         tg := testgo(t)
1362         defer tg.cleanup()
1363         tg.parallel()
1364         tg.tempDir("home/go")
1365         tg.setenv(homeEnvName(), tg.path("home"))
1366
1367         tg.run("env", "GOPATH")
1368         tg.grepStdout(regexp.QuoteMeta(tg.path("home/go")), "want GOPATH=$HOME/go")
1369
1370         tg.setenv("GOROOT", tg.path("home/go"))
1371         tg.run("env", "GOPATH")
1372         tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go")
1373
1374         tg.setenv("GOROOT", tg.path("home/go")+"/")
1375         tg.run("env", "GOPATH")
1376         tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go/")
1377 }
1378
1379 func TestDefaultGOPATHGet(t *testing.T) {
1380         testenv.MustHaveExternalNetwork(t)
1381         testenv.MustHaveExecPath(t, "git")
1382
1383         tg := testgo(t)
1384         defer tg.cleanup()
1385         tg.parallel()
1386         tg.setenv("GOPATH", "")
1387         tg.tempDir("home")
1388         tg.setenv(homeEnvName(), tg.path("home"))
1389
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")
1393
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")
1399
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")
1405 }
1406
1407 func TestDefaultGOPATHPrintedSearchList(t *testing.T) {
1408         tg := testgo(t)
1409         defer tg.cleanup()
1410         tg.parallel()
1411         tg.setenv("GOPATH", "")
1412         tg.tempDir("home")
1413         tg.setenv(homeEnvName(), tg.path("home"))
1414
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")
1417 }
1418
1419 func TestLdflagsArgumentsWithSpacesIssue3941(t *testing.T) {
1420         skipIfGccgo(t, "gccgo does not support -ldflags -X")
1421         tooSlow(t)
1422         tg := testgo(t)
1423         defer tg.cleanup()
1424         tg.parallel()
1425         tg.tempFile("main.go", `package main
1426                 var extern string
1427                 func main() {
1428                         println(extern)
1429                 }`)
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`)
1432 }
1433
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")
1438         tooSlow(t)
1439         tg := testgo(t)
1440         defer tg.cleanup()
1441         tg.parallel()
1442         tg.tempFile("main.go", `package main
1443                 var extern string
1444                 func main() {
1445                         print(extern)
1446                 }`)
1447         testStr := "test test test test test \n\\ "
1448         var buf strings.Builder
1449         for buf.Len() < sys.ExecArgLengthLimit+1 {
1450                 buf.WriteString(testStr)
1451         }
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")
1455         }
1456 }
1457
1458 func TestGoTestDashCDashOControlsBinaryLocation(t *testing.T) {
1459         skipIfGccgo(t, "gccgo has no standard packages")
1460         tooSlow(t)
1461         tg := testgo(t)
1462         defer tg.cleanup()
1463         tg.parallel()
1464         tg.makeTempdir()
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")
1467 }
1468
1469 func TestGoTestDashOWritesBinary(t *testing.T) {
1470         skipIfGccgo(t, "gccgo has no standard packages")
1471         tooSlow(t)
1472         tg := testgo(t)
1473         defer tg.cleanup()
1474         tg.parallel()
1475         tg.makeTempdir()
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")
1478 }
1479
1480 // Issue 4515.
1481 func TestInstallWithTags(t *testing.T) {
1482         tooSlow(t)
1483         tg := testgo(t)
1484         defer tg.cleanup()
1485         tg.parallel()
1486         tg.tempDir("bin")
1487         tg.tempFile("src/example/a/main.go", `package main
1488                 func main() {}`)
1489         tg.tempFile("src/example/b/main.go", `// +build mytag
1490
1491                 package main
1492                 func main() {}`)
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")
1505         }
1506 }
1507
1508 // Issue 17451, 17662.
1509 func TestSymlinkWarning(t *testing.T) {
1510         tg := testgo(t)
1511         defer tg.cleanup()
1512         tg.parallel()
1513         tg.makeTempdir()
1514         tg.setenv("GOPATH", tg.path("."))
1515
1516         tg.tempDir("src/example/xx")
1517         tg.tempDir("yy/zz")
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)
1521         }
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")
1526
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")
1531 }
1532
1533 func TestCgoShowsFullPathNames(t *testing.T) {
1534         if !canCgo {
1535                 t.Skip("skipping because cgo not enabled")
1536         }
1537
1538         tg := testgo(t)
1539         defer tg.cleanup()
1540         tg.parallel()
1541         tg.tempFile("src/x/y/dirname/foo.go", `
1542                 package foo
1543                 import "C"
1544                 func f() {`)
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")
1548 }
1549
1550 func TestCgoHandlesWlORIGIN(t *testing.T) {
1551         tooSlow(t)
1552         if !canCgo {
1553                 t.Skip("skipping because cgo not enabled")
1554         }
1555
1556         tg := testgo(t)
1557         defer tg.cleanup()
1558         tg.parallel()
1559         tg.tempFile("src/origin/origin.go", `package origin
1560                 // #cgo !darwin,!windows LDFLAGS: -Wl,-rpath,$ORIGIN
1561                 // void f(void) {}
1562                 import "C"
1563                 func f() { C.f() }`)
1564         tg.setenv("GOPATH", tg.path("."))
1565         tg.run("build", "origin")
1566 }
1567
1568 func TestCgoPkgConfig(t *testing.T) {
1569         tooSlow(t)
1570         if !canCgo {
1571                 t.Skip("skipping because cgo not enabled")
1572         }
1573         tg := testgo(t)
1574         defer tg.cleanup()
1575         tg.parallel()
1576
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)
1582         }
1583
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", `
1589 Name: foo
1590 Description: The foo library
1591 Version: 1.0.0
1592 Cflags: -Dhello=10 -Dworld=+32 -DDEFINED_FROM_PKG_CONFIG=hello\ world
1593 `)
1594         tg.tempFile("foo.go", `package main
1595
1596 /*
1597 #cgo pkg-config: foo
1598 int value() {
1599         return DEFINED_FROM_PKG_CONFIG;
1600 }
1601 */
1602 import "C"
1603 import "os"
1604
1605 func main() {
1606         if C.value() != 42 {
1607                 println("value() =", C.value(), "wanted 42")
1608                 os.Exit(1)
1609         }
1610 }
1611 `)
1612         tg.setenv("PKG_CONFIG_PATH", tg.path("."))
1613         tg.run("run", tg.path("foo.go"))
1614 }
1615
1616 func TestListTemplateContextFunction(t *testing.T) {
1617         t.Parallel()
1618         for _, tt := range []struct {
1619                 v    string
1620                 want string
1621         }{
1622                 {"GOARCH", runtime.GOARCH},
1623                 {"GOOS", runtime.GOOS},
1624                 {"GOROOT", testGOROOT},
1625                 {"GOPATH", os.Getenv("GOPATH")},
1626                 {"CgoEnabled", ""},
1627                 {"UseAllFiles", ""},
1628                 {"Compiler", ""},
1629                 {"BuildTags", ""},
1630                 {"ReleaseTags", ""},
1631                 {"InstallSuffix", ""},
1632         } {
1633                 tt := tt
1634                 t.Run(tt.v, func(t *testing.T) {
1635                         tg := testgo(t)
1636                         tg.parallel()
1637                         defer tg.cleanup()
1638                         tmpl := "{{context." + tt.v + "}}"
1639                         tg.run("list", "-f", tmpl)
1640                         if tt.want == "" {
1641                                 return
1642                         }
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)
1645                         }
1646                 })
1647         }
1648 }
1649
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) {
1654         tooSlow(t)
1655
1656         tg := testgo(t)
1657         tg.parallel()
1658         defer tg.cleanup()
1659
1660         tg.tempFile("src/dir/x/x.go", `package x
1661                 var X int
1662         `)
1663         tg.setenv("GOPATH", tg.path("."))
1664         tg.run("build", "dir/x")
1665
1666         // Ordinary import should work.
1667         tg.tempFile("src/dir/p0/p.go", `package p0
1668                 import "dir/x"
1669                 var _ = x.X
1670         `)
1671         tg.run("build", "dir/p0")
1672
1673         // Relative import should not.
1674         tg.tempFile("src/dir/p1/p.go", `package p1
1675                 import "../x"
1676                 var _ = x.X
1677         `)
1678         tg.runFail("build", "dir/p1")
1679         tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1680
1681         // ... even in a test.
1682         tg.tempFile("src/dir/p2/p.go", `package p2
1683         `)
1684         tg.tempFile("src/dir/p2/p_test.go", `package p2
1685                 import "../x"
1686                 import "testing"
1687                 var _ = x.X
1688                 func TestFoo(t *testing.T) {}
1689         `)
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")
1693
1694         // ... even in an xtest.
1695         tg.tempFile("src/dir/p2/p_test.go", `package p2_test
1696                 import "../x"
1697                 import "testing"
1698                 var _ = x.X
1699                 func TestFoo(t *testing.T) {}
1700         `)
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")
1704
1705         // Relative import starting with ./ should not work either.
1706         tg.tempFile("src/dir/d.go", `package dir
1707                 import "./x"
1708                 var _ = x.X
1709         `)
1710         tg.runFail("build", "dir")
1711         tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1712
1713         // ... even in a test.
1714         tg.tempFile("src/dir/d.go", `package dir
1715         `)
1716         tg.tempFile("src/dir/d_test.go", `package dir
1717                 import "./x"
1718                 import "testing"
1719                 var _ = x.X
1720                 func TestFoo(t *testing.T) {}
1721         `)
1722         tg.run("build", "dir")
1723         tg.runFail("test", "dir")
1724         tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1725
1726         // ... even in an xtest.
1727         tg.tempFile("src/dir/d_test.go", `package dir_test
1728                 import "./x"
1729                 import "testing"
1730                 var _ = x.X
1731                 func TestFoo(t *testing.T) {}
1732         `)
1733         tg.run("build", "dir")
1734         tg.runFail("test", "dir")
1735         tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1736
1737         // Relative import plain ".." should not work.
1738         tg.tempFile("src/dir/x/y/y.go", `package dir
1739                 import ".."
1740                 var _ = x.X
1741         `)
1742         tg.runFail("build", "dir/x/y")
1743         tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1744
1745         // ... even in a test.
1746         tg.tempFile("src/dir/x/y/y.go", `package y
1747         `)
1748         tg.tempFile("src/dir/x/y/y_test.go", `package y
1749                 import ".."
1750                 import "testing"
1751                 var _ = x.X
1752                 func TestFoo(t *testing.T) {}
1753         `)
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")
1757
1758         // ... even in an x test.
1759         tg.tempFile("src/dir/x/y/y_test.go", `package y_test
1760                 import ".."
1761                 import "testing"
1762                 var _ = x.X
1763                 func TestFoo(t *testing.T) {}
1764         `)
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")
1768
1769         // Relative import "." should not work.
1770         tg.tempFile("src/dir/x/xx.go", `package x
1771                 import "."
1772                 var _ = x.X
1773         `)
1774         tg.runFail("build", "dir/x")
1775         tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
1776
1777         // ... even in a test.
1778         tg.tempFile("src/dir/x/xx.go", `package x
1779         `)
1780         tg.tempFile("src/dir/x/xx_test.go", `package x
1781                 import "."
1782                 import "testing"
1783                 var _ = x.X
1784                 func TestFoo(t *testing.T) {}
1785         `)
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")
1789
1790         // ... even in an xtest.
1791         tg.tempFile("src/dir/x/xx.go", `package x
1792         `)
1793         tg.tempFile("src/dir/x/xx_test.go", `package x_test
1794                 import "."
1795                 import "testing"
1796                 var _ = x.X
1797                 func TestFoo(t *testing.T) {}
1798         `)
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")
1802 }
1803
1804 func TestGoInstallPkgdir(t *testing.T) {
1805         skipIfGccgo(t, "gccgo has no standard packages")
1806         if !canCgo {
1807                 // Only the stdlib packages that use cgo have install
1808                 // targets, (we're using net below) so cgo is required
1809                 // for the install.
1810                 t.Skip("skipping because cgo not enabled")
1811         }
1812         tooSlow(t)
1813
1814         tg := testgo(t)
1815         tg.parallel()
1816         tg.setenv("GODEBUG", "installgoroot=all")
1817         defer tg.cleanup()
1818         tg.makeTempdir()
1819         pkg := tg.path(".")
1820         tg.run("install", "-pkgdir", pkg, "net")
1821         tg.mustExist(filepath.Join(pkg, "net.a"))
1822         tg.mustNotExist(filepath.Join(pkg, "runtime/cgo.a"))
1823 }
1824
1825 // For issue 14337.
1826 func TestParallelTest(t *testing.T) {
1827         tooSlow(t)
1828         tg := testgo(t)
1829         tg.parallel()
1830         defer tg.cleanup()
1831         tg.makeTempdir()
1832         const testSrc = `package package_test
1833                 import (
1834                         "testing"
1835                 )
1836                 func TestTest(t *testing.T) {
1837                 }`
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")
1844 }
1845
1846 func TestBinaryOnlyPackages(t *testing.T) {
1847         tooSlow(t)
1848
1849         tg := testgo(t)
1850         defer tg.cleanup()
1851         tg.parallel()
1852         tg.makeTempdir()
1853         tg.setenv("GOPATH", tg.path("."))
1854
1855         tg.tempFile("src/p1/p1.go", `//go:binary-only-package
1856
1857                 package p1
1858         `)
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")
1862
1863         tg.tempFile("src/p1/p1.go", `
1864                 package p1
1865                 import "fmt"
1866                 func F(b bool) { fmt.Printf("hello from p1\n"); if b { F(false) } }
1867         `)
1868         tg.run("install", "p1")
1869         os.Remove(tg.path("src/p1/p1.go"))
1870         tg.mustNotExist(tg.path("src/p1/p1.go"))
1871
1872         tg.tempFile("src/p2/p2.go", `//go:binary-only-packages-are-not-great
1873
1874                 package p2
1875                 import "p1"
1876                 func F() { p1.F(true) }
1877         `)
1878         tg.runFail("install", "p2")
1879         tg.grepStderr("no Go files", "did not complain about missing sources")
1880
1881         tg.tempFile("src/p1/missing.go", `//go:binary-only-package
1882
1883                 package p1
1884                 import _ "fmt"
1885                 func G()
1886         `)
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")
1890
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")
1894 }
1895
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")
1900         }
1901
1902         tg := testgo(t)
1903         defer tg.cleanup()
1904         tg.parallel()
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("."))
1909
1910         // We should see the .syso file regardless of the setting of
1911         // CGO_ENABLED.
1912
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")
1916
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")
1920
1921         tg.setenv("CGO_ENABLED", "1")
1922         tg.run("list", "-msan", "-f", "{{.SysoFiles}}", "syso")
1923         tg.grepStdoutNot("a.syso", "unexpected syso file with -msan")
1924 }
1925
1926 // Issue 16120.
1927 func TestGenerateUsesBuildContext(t *testing.T) {
1928         if runtime.GOOS == "windows" {
1929                 t.Skip("this test won't run under Windows")
1930         }
1931
1932         tg := testgo(t)
1933         defer tg.cleanup()
1934         tg.parallel()
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("."))
1938
1939         tg.setenv("GOOS", "linux")
1940         tg.setenv("GOARCH", "amd64")
1941         tg.run("generate", "gen")
1942         tg.grepStdout("linux amd64", "unexpected GOOS/GOARCH combination")
1943
1944         tg.setenv("GOOS", "darwin")
1945         tg.setenv("GOARCH", "arm64")
1946         tg.run("generate", "gen")
1947         tg.grepStdout("darwin arm64", "unexpected GOOS/GOARCH combination")
1948 }
1949
1950 func TestGoEnv(t *testing.T) {
1951         tg := testgo(t)
1952         tg.parallel()
1953         defer tg.cleanup()
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")
1958
1959         tg.run("env", "GCCGO")
1960         tg.grepStdout(".", "GCCGO unexpectedly empty")
1961
1962         tg.run("env", "CGO_CFLAGS")
1963         tg.grepStdout(".", "default CGO_CFLAGS unexpectedly empty")
1964
1965         tg.setenv("CGO_CFLAGS", "-foobar")
1966         tg.run("env", "CGO_CFLAGS")
1967         tg.grepStdout("^-foobar$", "CGO_CFLAGS not honored")
1968
1969         tg.setenv("CC", "gcc -fmust -fgo -ffaster")
1970         tg.run("env", "CC")
1971         tg.grepStdout("gcc", "CC not found")
1972         tg.run("env", "GOGCCFLAGS")
1973         tg.grepStdout("-ffaster", "CC arguments not found")
1974
1975         tg.run("env", "GOVERSION")
1976         envVersion := strings.TrimSpace(tg.stdout.String())
1977
1978         tg.run("version")
1979         cmdVersion := strings.TrimSpace(tg.stdout.String())
1980
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)
1985         }
1986 }
1987
1988 const (
1989         noMatchesPattern = `(?m)^ok.*\[no tests to run\]`
1990         okPattern        = `(?m)^ok`
1991 )
1992
1993 // Issue 18044.
1994 func TestLdBindNow(t *testing.T) {
1995         tg := testgo(t)
1996         defer tg.cleanup()
1997         tg.parallel()
1998         tg.setenv("LD_BIND_NOW", "1")
1999         tg.run("help")
2000 }
2001
2002 // Issue 18225.
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")
2006         tg := testgo(t)
2007         defer tg.cleanup()
2008         tg.parallel()
2009         asm := `DATA ·constants<>+0x0(SB)/8,$0
2010 GLOBL ·constants<>(SB),8,$8
2011 `
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")
2017 }
2018
2019 // Issue 18975.
2020 func TestFFLAGS(t *testing.T) {
2021         if !canCgo {
2022                 t.Skip("skipping because cgo not enabled")
2023         }
2024
2025         tg := testgo(t)
2026         defer tg.cleanup()
2027         tg.parallel()
2028
2029         tg.tempFile("p/src/p/main.go", `package main
2030                 // #cgo FFLAGS: -no-such-fortran-flag
2031                 import "C"
2032                 func main() {}
2033         `)
2034         tg.tempFile("p/src/p/a.f", `! comment`)
2035         tg.setenv("GOPATH", tg.path("p"))
2036
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"})
2041
2042         tg.grepStderr("no-such-fortran-flag", `missing expected "-no-such-fortran-flag"`)
2043 }
2044
2045 // Issue 19198.
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")
2049         tooSlow(t)
2050         if runtime.GOARCH != "386" && runtime.GOARCH != "amd64" {
2051                 t.Skipf("skipping test on %s", runtime.GOARCH)
2052         }
2053         if !canCgo {
2054                 t.Skip("skipping because cgo not enabled")
2055         }
2056
2057         tg := testgo(t)
2058         defer tg.cleanup()
2059         tg.parallel()
2060
2061         asm := `
2062 #include "textflag.h"
2063
2064 DATA sym<>+0x0(SB)/8,$0
2065 GLOBL sym<>(SB),(NOPTR+RODATA),$8
2066
2067 TEXT ·Data(SB),NOSPLIT,$0
2068         MOVB sym<>(SB), AX
2069         MOVB AX, ret+0(FP)
2070         RET
2071 `
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", `
2077 package main
2078 import "a"
2079 import "b"
2080 import "C"
2081 func main() {
2082         _ = a.Data() + b.Data()
2083 }
2084 `)
2085         tg.setenv("GOPATH", tg.path("go"))
2086         exe := tg.path("p.exe")
2087         tg.creatingTemp(exe)
2088         tg.run("build", "-o", exe, "p")
2089 }
2090
2091 func copyFile(src, dst string, perm fs.FileMode) error {
2092         sf, err := os.Open(src)
2093         if err != nil {
2094                 return err
2095         }
2096         defer sf.Close()
2097
2098         df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
2099         if err != nil {
2100                 return err
2101         }
2102
2103         _, err = io.Copy(df, sf)
2104         err2 := df.Close()
2105         if err != nil {
2106                 return err
2107         }
2108         return err2
2109 }
2110
2111 func TestNeedVersion(t *testing.T) {
2112         skipIfGccgo(t, "gccgo does not use cmd/compile")
2113         tg := testgo(t)
2114         defer tg.cleanup()
2115         tg.parallel()
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")
2121 }
2122
2123 func TestBuildmodePIE(t *testing.T) {
2124         if testing.Short() && testenv.Builder() == "" {
2125                 t.Skipf("skipping in -short mode on non-builder")
2126         }
2127
2128         platform := fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)
2129         switch platform {
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",
2132                 "freebsd/amd64",
2133                 "windows/386", "windows/amd64", "windows/arm":
2134         case "darwin/amd64":
2135         default:
2136                 t.Skipf("skipping test because buildmode=pie is not supported on %s", platform)
2137         }
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")
2141         }
2142         t.Run("non-cgo", func(t *testing.T) {
2143                 testBuildmodePIE(t, false, true)
2144         })
2145         if canCgo {
2146                 switch runtime.GOOS {
2147                 case "darwin", "freebsd", "linux", "windows":
2148                         t.Run("cgo", func(t *testing.T) {
2149                                 testBuildmodePIE(t, true, true)
2150                         })
2151                 }
2152         }
2153 }
2154
2155 func TestWindowsDefaultBuildmodIsPIE(t *testing.T) {
2156         if testing.Short() && testenv.Builder() == "" {
2157                 t.Skipf("skipping in -short mode on non-builder")
2158         }
2159
2160         if runtime.GOOS != "windows" {
2161                 t.Skip("skipping windows only test")
2162         }
2163
2164         t.Run("non-cgo", func(t *testing.T) {
2165                 testBuildmodePIE(t, false, false)
2166         })
2167         if canCgo {
2168                 t.Run("cgo", func(t *testing.T) {
2169                         testBuildmodePIE(t, true, false)
2170                 })
2171         }
2172 }
2173
2174 func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) {
2175         tg := testgo(t)
2176         defer tg.cleanup()
2177         tg.parallel()
2178
2179         var s string
2180         if useCgo {
2181                 s = `import "C";`
2182         }
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")
2189         }
2190         args = append(args, "-o", obj, src)
2191         tg.run(args...)
2192
2193         switch runtime.GOOS {
2194         case "linux", "android", "freebsd":
2195                 f, err := elf.Open(obj)
2196                 if err != nil {
2197                         t.Fatal(err)
2198                 }
2199                 defer f.Close()
2200                 if f.Type != elf.ET_DYN {
2201                         t.Errorf("PIE type must be ET_DYN, but %s", f.Type)
2202                 }
2203         case "darwin":
2204                 f, err := macho.Open(obj)
2205                 if err != nil {
2206                         t.Fatal(err)
2207                 }
2208                 defer f.Close()
2209                 if f.Flags&macho.FlagDyldLink == 0 {
2210                         t.Error("PIE must have DyldLink flag, but not")
2211                 }
2212                 if f.Flags&macho.FlagPIE == 0 {
2213                         t.Error("PIE must have PIE flag, but not")
2214                 }
2215         case "windows":
2216                 f, err := pe.Open(obj)
2217                 if err != nil {
2218                         t.Fatal(err)
2219                 }
2220                 defer f.Close()
2221                 if f.Section(".reloc") == nil {
2222                         t.Error(".reloc section is not present")
2223                 }
2224                 if (f.FileHeader.Characteristics & pe.IMAGE_FILE_RELOCS_STRIPPED) != 0 {
2225                         t.Error("IMAGE_FILE_RELOCS_STRIPPED flag is set")
2226                 }
2227                 var dc uint16
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")
2235                         }
2236                 default:
2237                         t.Fatalf("unexpected optional header type of %T", f.OptionalHeader)
2238                 }
2239                 if (dc & pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 {
2240                         t.Error("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag is not set")
2241                 }
2242                 if useCgo {
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")
2249                         if section == nil {
2250                                 t.Skip(".edata section is not present")
2251                         }
2252                         // TODO: deduplicate this struct from cmd/link/internal/ld/pe.go
2253                         type IMAGE_EXPORT_DIRECTORY struct {
2254                                 _                 [2]uint32
2255                                 _                 [2]uint16
2256                                 _                 [2]uint32
2257                                 NumberOfFunctions uint32
2258                                 NumberOfNames     uint32
2259                                 _                 [3]uint32
2260                         }
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)
2264                         }
2265
2266                         // Only _cgo_dummy_export should be exported
2267                         if e.NumberOfFunctions != 1 {
2268                                 t.Fatalf("got %d exported functions; want 1", e.NumberOfFunctions)
2269                         }
2270                         if e.NumberOfNames != 1 {
2271                                 t.Fatalf("got %d exported names; want 1", e.NumberOfNames)
2272                         }
2273                 }
2274         default:
2275                 panic("unreachable")
2276         }
2277
2278         out, err := exec.Command(obj).CombinedOutput()
2279         if err != nil {
2280                 t.Fatal(err)
2281         }
2282
2283         if string(out) != "hello" {
2284                 t.Errorf("got %q; want %q", out, "hello")
2285         }
2286 }
2287
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)
2292         }
2293
2294         testenv.MustHaveExecPath(t, "upx")
2295         out, err := exec.Command("upx", "--version").CombinedOutput()
2296         if err != nil {
2297                 t.Fatalf("upx --version failed: %v", err)
2298         }
2299
2300         // upx --version prints `upx <version>` in the first line of output:
2301         //   upx 3.94
2302         //   [...]
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)
2307         }
2308
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])
2313         }
2314
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)
2318         }
2319
2320         tg := testgo(t)
2321         defer tg.cleanup()
2322         tg.parallel()
2323
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)
2328
2329         out, err = exec.Command("upx", obj).CombinedOutput()
2330         if err != nil {
2331                 t.Logf("executing upx\n%s\n", out)
2332                 t.Fatalf("upx failed with %v", err)
2333         }
2334
2335         out, err = exec.Command(obj).CombinedOutput()
2336         if err != nil {
2337                 t.Logf("%s", out)
2338                 t.Fatalf("running compressed go binary failed with error %s", err)
2339         }
2340         if string(out) != "hello upx" {
2341                 t.Fatalf("bad output from compressed go binary:\ngot %q; want %q", out, "hello upx")
2342         }
2343 }
2344
2345 func TestCacheListStale(t *testing.T) {
2346         tooSlow(t)
2347         if godebug.Get("gocacheverify") == "1" {
2348                 t.Skip("GODEBUG gocacheverify")
2349         }
2350         tg := testgo(t)
2351         defer tg.cleanup()
2352         tg.parallel()
2353         tg.makeTempdir()
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")
2358
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")
2365 }
2366
2367 func TestCacheCoverage(t *testing.T) {
2368         tooSlow(t)
2369
2370         if godebug.Get("gocacheverify") == "1" {
2371                 t.Skip("GODEBUG gocacheverify")
2372         }
2373
2374         tg := testgo(t)
2375         defer tg.cleanup()
2376         tg.parallel()
2377         tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
2378         tg.makeTempdir()
2379
2380         tg.setenv("GOCACHE", tg.path("c1"))
2381         tg.run("test", "-cover", "-short", "strings")
2382         tg.run("test", "-cover", "-short", "math", "strings")
2383 }
2384
2385 func TestIssue22588(t *testing.T) {
2386         // Don't get confused by stderr coming from tools.
2387         tg := testgo(t)
2388         defer tg.cleanup()
2389         tg.parallel()
2390
2391         tg.wantNotStale("runtime", "", "must be non-stale to compare staleness under -toolexec")
2392
2393         if _, err := os.Stat("/usr/bin/time"); err != nil {
2394                 t.Skip(err)
2395         }
2396
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")
2400 }
2401
2402 func TestIssue22531(t *testing.T) {
2403         tooSlow(t)
2404         if godebug.Get("gocacheverify") == "1" {
2405                 t.Skip("GODEBUG gocacheverify")
2406         }
2407         tg := testgo(t)
2408         defer tg.cleanup()
2409         tg.parallel()
2410         tg.makeTempdir()
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))
2418
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))
2429 }
2430
2431 func TestIssue22596(t *testing.T) {
2432         tooSlow(t)
2433         if godebug.Get("gocacheverify") == "1" {
2434                 t.Skip("GODEBUG gocacheverify")
2435         }
2436         tg := testgo(t)
2437         defer tg.cleanup()
2438         tg.parallel()
2439         tg.makeTempdir()
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")
2443
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")
2449
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")
2458 }
2459
2460 func TestTestCache(t *testing.T) {
2461         tooSlow(t)
2462
2463         if godebug.Get("gocacheverify") == "1" {
2464                 t.Skip("GODEBUG gocacheverify")
2465         }
2466         tg := testgo(t)
2467         defer tg.cleanup()
2468         tg.parallel()
2469         tg.makeTempdir()
2470         tg.setenv("GOPATH", tg.tempdir)
2471         tg.setenv("GOCACHE", tg.path("cache"))
2472
2473         // The -p=1 in the commands below just makes the -x output easier to read.
2474
2475         t.Log("\n\nINITIAL\n\n")
2476
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/...")
2484
2485         t.Log("\n\nREPEAT\n\n")
2486
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")
2495
2496         t.Log("\n\nCOMMENT\n\n")
2497
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")
2509
2510         t.Log("\n\nCHANGE\n\n")
2511
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/...")
2515
2516         // p2 should have been rebuilt.
2517         tg.grepStderr(`([\\/]compile|gccgo).*p2.go`, "did not recompile p2")
2518
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")
2523
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")
2533         }
2534
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")
2540
2541         // t4 imports p2, but p2 did not change, so t4 should be relinked, not recompiled,
2542         // and not rerun.
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")
2549         }
2550 }
2551
2552 func TestTestSkipVetAfterFailedBuild(t *testing.T) {
2553         tg := testgo(t)
2554         defer tg.cleanup()
2555         tg.parallel()
2556
2557         tg.tempFile("x_test.go", `package x
2558                 func f() {
2559                         return 1
2560                 }
2561         `)
2562
2563         tg.runFail("test", tg.path("x_test.go"))
2564         tg.grepStderrNot(`vet`, "vet should be skipped after the failed build")
2565 }
2566
2567 func TestTestVetRebuild(t *testing.T) {
2568         tooSlow(t)
2569         tg := testgo(t)
2570         defer tg.cleanup()
2571         tg.parallel()
2572
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
2578                 import "b"
2579                 type Type struct{}
2580                 func (*Type) M() b.T {return 0}
2581         `)
2582         tg.tempFile("src/b/b.go", `package b
2583                 type T int
2584                 type I interface {M() T}
2585         `)
2586         tg.tempFile("src/b/export_test.go", `package b
2587                 func (*T) Method() *T { return nil }
2588         `)
2589         tg.tempFile("src/b/b_test.go", `package b_test
2590                 import (
2591                         "testing"
2592                         "a"
2593                         . "b"
2594                 )
2595                 func TestBroken(t *testing.T) {
2596                         x := new(T)
2597                         x.Method()
2598                         _ = new(a.Type)
2599                 }
2600         `)
2601
2602         tg.setenv("GOPATH", tg.path("."))
2603         tg.run("test", "b")
2604         tg.run("vet", "b")
2605 }
2606
2607 func TestInstallDeps(t *testing.T) {
2608         tooSlow(t)
2609         tg := testgo(t)
2610         defer tg.cleanup()
2611         tg.parallel()
2612         tg.makeTempdir()
2613         tg.setenv("GOPATH", tg.tempdir)
2614
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")
2618
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())
2625
2626         tg.run("install", "main1")
2627
2628         tg.mustExist(main1)
2629         tg.mustNotExist(p2)
2630         tg.mustNotExist(p1)
2631
2632         tg.run("install", "p2")
2633         tg.mustExist(p2)
2634         tg.mustNotExist(p1)
2635 }
2636
2637 // Issue 22986.
2638 func TestImportPath(t *testing.T) {
2639         tooSlow(t)
2640         tg := testgo(t)
2641         defer tg.cleanup()
2642         tg.parallel()
2643
2644         tg.tempFile("src/a/a.go", `
2645 package main
2646
2647 import (
2648         "log"
2649         p "a/p-1.0"
2650 )
2651
2652 func main() {
2653         if !p.V {
2654                 log.Fatal("false")
2655         }
2656 }`)
2657
2658         tg.tempFile("src/a/a_test.go", `
2659 package main_test
2660
2661 import (
2662         p "a/p-1.0"
2663         "testing"
2664 )
2665
2666 func TestV(t *testing.T) {
2667         if !p.V {
2668                 t.Fatal("false")
2669         }
2670 }`)
2671
2672         tg.tempFile("src/a/p-1.0/p.go", `
2673 package p
2674
2675 var V = true
2676
2677 func init() {}
2678 `)
2679
2680         tg.setenv("GOPATH", tg.path("."))
2681         tg.run("build", "-o", tg.path("a.exe"), "a")
2682         tg.run("test", "a")
2683 }
2684
2685 func TestBadCommandLines(t *testing.T) {
2686         tg := testgo(t)
2687         defer tg.cleanup()
2688         tg.parallel()
2689
2690         tg.tempFile("src/x/x.go", "package x\n")
2691         tg.setenv("GOPATH", tg.path("."))
2692
2693         tg.run("build", "x")
2694
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")))
2699
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")))
2704
2705         if runtime.Compiler == "gccgo" {
2706                 tg.runFail("build", "-gccgoflags=all=@x", "x")
2707         } else {
2708                 tg.runFail("build", "-gcflags=all=@x", "x")
2709         }
2710         tg.grepStderr("invalid command-line argument @x in command", "did not reject @x during exec")
2711
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")
2716
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")
2721
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")
2726
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")
2731 }
2732
2733 func TestTwoPkgConfigs(t *testing.T) {
2734         if !canCgo {
2735                 t.Skip("no cgo")
2736         }
2737         if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
2738                 t.Skipf("no shell scripts on %s", runtime.GOOS)
2739         }
2740         tooSlow(t)
2741         tg := testgo(t)
2742         defer tg.cleanup()
2743         tg.parallel()
2744         tg.tempFile("src/x/a.go", `package x
2745                 // #cgo pkg-config: --static a
2746                 import "C"
2747         `)
2748         tg.tempFile("src/x/b.go", `package x
2749                 // #cgo pkg-config: --static a
2750                 import "C"
2751         `)
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"))
2759         tg.must(err)
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)
2764         }
2765 }
2766
2767 func TestCgoCache(t *testing.T) {
2768         if !canCgo {
2769                 t.Skip("no cgo")
2770         }
2771         tooSlow(t)
2772
2773         tg := testgo(t)
2774         defer tg.cleanup()
2775         tg.parallel()
2776         tg.tempFile("src/x/a.go", `package main
2777                 // #ifndef VAL
2778                 // #define VAL 0
2779                 // #endif
2780                 // int val = VAL;
2781                 import "C"
2782                 import "fmt"
2783                 func main() { fmt.Println(C.val) }
2784         `)
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")
2791 }
2792
2793 // Issue 23982
2794 func TestFilepathUnderCwdFormat(t *testing.T) {
2795         tg := testgo(t)
2796         defer tg.cleanup()
2797         tg.parallel()
2798         tg.run("test", "-x", "-cover", "log")
2799         tg.grepStderrNot(`\.log\.cover\.go`, "-x output should contain correctly formatted filepath under cwd")
2800 }
2801
2802 // Issue 24396.
2803 func TestDontReportRemoveOfEmptyDir(t *testing.T) {
2804         tg := testgo(t)
2805         defer tg.cleanup()
2806         tg.parallel()
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,
2812         // nothing else.
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")
2815         }
2816 }
2817
2818 // Issue 24704.
2819 func TestLinkerTmpDirIsDeleted(t *testing.T) {
2820         skipIfGccgo(t, "gccgo does not use cmd/link")
2821         if !canCgo {
2822                 t.Skip("skipping because cgo not enabled")
2823         }
2824         tooSlow(t)
2825
2826         tg := testgo(t)
2827         defer tg.cleanup()
2828         tg.parallel()
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:") {
2836                         continue
2837                 }
2838                 hostLinkLine = line
2839                 break
2840         }
2841         if hostLinkLine == "" {
2842                 t.Fatal(`fail to find with "host link:" string in linker output`)
2843         }
2844         // Find parameter, like "/tmp/go-link-408556474/go.o" inside of
2845         // "host link:" line, and extract temp directory /tmp/go-link-408556474
2846         // out of it.
2847         tmpdir := hostLinkLine
2848         i := strings.Index(tmpdir, `go.o"`)
2849         if i == -1 {
2850                 t.Fatalf(`fail to find "go.o" in "host link:" line %q`, hostLinkLine)
2851         }
2852         tmpdir = tmpdir[:i-1]
2853         i = strings.LastIndex(tmpdir, `"`)
2854         if i == -1 {
2855                 t.Fatalf(`fail to find " in "host link:" line %q`, hostLinkLine)
2856         }
2857         tmpdir = tmpdir[i+1:]
2858         // Verify that temp directory has been removed.
2859         _, err := os.Stat(tmpdir)
2860         if err == nil {
2861                 t.Fatalf("temp directory %q has not been removed", tmpdir)
2862         }
2863         if !os.IsNotExist(err) {
2864                 t.Fatalf("Stat(%q) returns unexpected error: %v", tmpdir, err)
2865         }
2866 }
2867
2868 // Issue 25093.
2869 func TestCoverpkgTestOnly(t *testing.T) {
2870         skipIfGccgo(t, "gccgo has no cover tool")
2871         tooSlow(t)
2872         tg := testgo(t)
2873         defer tg.cleanup()
2874         tg.parallel()
2875         tg.tempFile("src/a/a.go", `package a
2876                 func F(i int) int {
2877                         return i*i
2878                 }`)
2879         tg.tempFile("src/atest/a_test.go", `
2880                 package a_test
2881                 import ( "a"; "testing" )
2882                 func TestF(t *testing.T) { a.F(2) }
2883         `)
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")
2888 }
2889
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)
2898         }
2899         tg := testgo(t)
2900         defer tg.cleanup()
2901
2902         wd, err := os.Getwd()
2903         tg.check(err)
2904         tg.makeTempdir()
2905         tg.check(os.Chdir(tg.tempdir))
2906         defer func() { tg.check(os.Chdir(wd)) }()
2907
2908         tg.check(os.Remove(tg.tempdir))
2909
2910         // `go version` should not fail
2911         tg.run("version")
2912 }
2913
2914 // A missing C compiler should not force the net package to be stale.
2915 // Issue 47215.
2916 func TestMissingCC(t *testing.T) {
2917         if !canCgo {
2918                 t.Skip("test is only meaningful on systems with cgo")
2919         }
2920         cc := os.Getenv("CC")
2921         if cc == "" {
2922                 cc = "gcc"
2923         }
2924         if filepath.IsAbs(cc) {
2925                 t.Skipf(`"CC" (%s) is an absolute path`, cc)
2926         }
2927         _, err := exec.LookPath(cc)
2928         if err != nil {
2929                 t.Skipf(`"CC" (%s) not on PATH`, cc)
2930         }
2931
2932         tg := testgo(t)
2933         defer tg.cleanup()
2934         netStale, _ := tg.isStale("net")
2935         if netStale {
2936                 t.Skip(`skipping test because "net" package is currently stale`)
2937         }
2938
2939         tg.setenv("PATH", "") // No C compiler on PATH.
2940         netStale, _ = tg.isStale("net")
2941         if netStale {
2942                 t.Error(`clearing "PATH" causes "net" to be stale`)
2943         }
2944 }