]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/go/go_test.go
[dev.boringcrypto] all: merge master into dev.boringcrypto
[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/testenv"
18         "io"
19         "io/fs"
20         "log"
21         "os"
22         "os/exec"
23         "path/filepath"
24         "regexp"
25         "runtime"
26         "strconv"
27         "strings"
28         "testing"
29         "time"
30
31         "cmd/go/internal/cache"
32         "cmd/go/internal/cfg"
33         "cmd/go/internal/robustio"
34         "cmd/go/internal/search"
35         "cmd/go/internal/work"
36         "cmd/internal/sys"
37
38         cmdgo "cmd/go"
39 )
40
41 func init() {
42         // GOVCS defaults to public:git|hg,private:all,
43         // which breaks many tests here - they can't use non-git, non-hg VCS at all!
44         // Change to fully permissive.
45         // The tests of the GOVCS setting itself are in ../../testdata/script/govcs.txt.
46         os.Setenv("GOVCS", "*:all")
47 }
48
49 var (
50         canRace          = false // whether we can run the race detector
51         canCgo           = false // whether we can use cgo
52         canMSan          = false // whether we can run the memory sanitizer
53         canASan          = false // whether we can run the address sanitizer
54         canFuzz          = false // whether we can search for new fuzz failures
55         fuzzInstrumented = false // whether fuzzing uses instrumentation
56 )
57
58 var exeSuffix string = func() string {
59         if runtime.GOOS == "windows" {
60                 return ".exe"
61         }
62         return ""
63 }()
64
65 func tooSlow(t *testing.T) {
66         if testing.Short() {
67                 // In -short mode; skip test, except run it on the {darwin,linux,windows}/amd64 builders.
68                 if testenv.Builder() != "" && runtime.GOARCH == "amd64" && (runtime.GOOS == "linux" || runtime.GOOS == "darwin" || runtime.GOOS == "windows") {
69                         return
70                 }
71                 t.Helper()
72                 t.Skip("skipping test in -short mode")
73         }
74 }
75
76 // testGOROOT is the GOROOT to use when running testgo, a cmd/go binary
77 // build from this process's current GOROOT, but run from a different
78 // (temp) directory.
79 var testGOROOT string
80
81 var testGOCACHE string
82
83 var testGo string
84 var testTmpDir string
85 var testBin string
86
87 // The TestMain function creates a go command for testing purposes and
88 // deletes it after the tests have been run.
89 func TestMain(m *testing.M) {
90         // When CMDGO_TEST_RUN_MAIN is set, we're reusing the test binary as cmd/go.
91         // Enable the special behavior needed in cmd/go/internal/work,
92         // run the main func exported via export_test.go, and exit.
93         // We set CMDGO_TEST_RUN_MAIN via os.Setenv and testScript.setup.
94         if os.Getenv("CMDGO_TEST_RUN_MAIN") != "" {
95                 if v := os.Getenv("TESTGO_VERSION"); v != "" {
96                         work.RuntimeVersion = v
97                 }
98
99                 if testGOROOT := os.Getenv("TESTGO_GOROOT"); testGOROOT != "" {
100                         // Disallow installs to the GOROOT from which testgo was built.
101                         // Installs to other GOROOTs — such as one set explicitly within a test — are ok.
102                         work.AllowInstall = func(a *work.Action) error {
103                                 if cfg.BuildN {
104                                         return nil
105                                 }
106
107                                 rel := search.InDir(a.Target, testGOROOT)
108                                 if rel == "" {
109                                         return nil
110                                 }
111
112                                 callerPos := ""
113                                 if _, file, line, ok := runtime.Caller(1); ok {
114                                         if shortFile := search.InDir(file, filepath.Join(testGOROOT, "src")); shortFile != "" {
115                                                 file = shortFile
116                                         }
117                                         callerPos = fmt.Sprintf("%s:%d: ", file, line)
118                                 }
119                                 return fmt.Errorf("%stestgo must not write to GOROOT (installing to %s)", callerPos, filepath.Join("GOROOT", rel))
120                         }
121                 }
122                 cmdgo.Main()
123                 os.Exit(0)
124         }
125         os.Setenv("CMDGO_TEST_RUN_MAIN", "true")
126
127         // $GO_GCFLAGS a compiler debug flag known to cmd/dist, make.bash, etc.
128         // It is not a standard go command flag; use os.Getenv, not cfg.Getenv.
129         if os.Getenv("GO_GCFLAGS") != "" {
130                 fmt.Fprintf(os.Stderr, "testing: warning: no tests to run\n") // magic string for cmd/go
131                 fmt.Printf("cmd/go test is not compatible with $GO_GCFLAGS being set\n")
132                 fmt.Printf("SKIP\n")
133                 return
134         }
135
136         flag.Parse()
137
138         if *proxyAddr != "" {
139                 StartProxy()
140                 select {}
141         }
142
143         // Run with a temporary TMPDIR to check that the tests don't
144         // leave anything behind.
145         topTmpdir, err := os.MkdirTemp("", "cmd-go-test-")
146         if err != nil {
147                 log.Fatal(err)
148         }
149         if !*testWork {
150                 defer removeAll(topTmpdir)
151         }
152         os.Setenv(tempEnvName(), topTmpdir)
153
154         dir, err := os.MkdirTemp(topTmpdir, "tmpdir")
155         if err != nil {
156                 log.Fatal(err)
157         }
158         testTmpDir = dir
159         if !*testWork {
160                 defer removeAll(testTmpDir)
161         }
162
163         testGOCACHE = cache.DefaultDir()
164         if testenv.HasGoBuild() {
165                 testBin = filepath.Join(testTmpDir, "testbin")
166                 if err := os.Mkdir(testBin, 0777); err != nil {
167                         log.Fatal(err)
168                 }
169                 testGo = filepath.Join(testBin, "go"+exeSuffix)
170                 gotool, err := testenv.GoTool()
171                 if err != nil {
172                         fmt.Fprintln(os.Stderr, "locating go tool: ", err)
173                         os.Exit(2)
174                 }
175
176                 goEnv := func(name string) string {
177                         out, err := exec.Command(gotool, "env", name).CombinedOutput()
178                         if err != nil {
179                                 fmt.Fprintf(os.Stderr, "go env %s: %v\n%s", name, err, out)
180                                 os.Exit(2)
181                         }
182                         return strings.TrimSpace(string(out))
183                 }
184                 testGOROOT = goEnv("GOROOT")
185                 os.Setenv("TESTGO_GOROOT", testGOROOT)
186                 // Ensure that GOROOT is set explicitly.
187                 // Otherwise, if the toolchain was built with GOROOT_FINAL set but has not
188                 // yet been moved to its final location, programs that invoke runtime.GOROOT
189                 // may accidentally use the wrong path.
190                 os.Setenv("GOROOT", testGOROOT)
191
192                 // The whole GOROOT/pkg tree was installed using the GOHOSTOS/GOHOSTARCH
193                 // toolchain (installed in GOROOT/pkg/tool/GOHOSTOS_GOHOSTARCH).
194                 // The testgo.exe we are about to create will be built for GOOS/GOARCH,
195                 // which means it will use the GOOS/GOARCH toolchain
196                 // (installed in GOROOT/pkg/tool/GOOS_GOARCH).
197                 // If these are not the same toolchain, then the entire standard library
198                 // will look out of date (the compilers in those two different tool directories
199                 // are built for different architectures and have different build IDs),
200                 // which will cause many tests to do unnecessary rebuilds and some
201                 // tests to attempt to overwrite the installed standard library.
202                 // Bail out entirely in this case.
203                 hostGOOS := goEnv("GOHOSTOS")
204                 hostGOARCH := goEnv("GOHOSTARCH")
205                 if hostGOOS != runtime.GOOS || hostGOARCH != runtime.GOARCH {
206                         fmt.Fprintf(os.Stderr, "testing: warning: no tests to run\n") // magic string for cmd/go
207                         fmt.Printf("cmd/go test is not compatible with GOOS/GOARCH != GOHOSTOS/GOHOSTARCH (%s/%s != %s/%s)\n", runtime.GOOS, runtime.GOARCH, hostGOOS, hostGOARCH)
208                         fmt.Printf("SKIP\n")
209                         return
210                 }
211
212                 // Duplicate the test executable into the path at testGo, for $PATH.
213                 // If the OS supports symlinks, use them instead of copying bytes.
214                 testExe, err := os.Executable()
215                 if err != nil {
216                         log.Fatal(err)
217                 }
218                 if err := os.Symlink(testExe, testGo); err != nil {
219                         // Otherwise, copy the bytes.
220                         src, err := os.Open(testExe)
221                         if err != nil {
222                                 log.Fatal(err)
223                         }
224                         defer src.Close()
225
226                         dst, err := os.OpenFile(testGo, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o777)
227                         if err != nil {
228                                 log.Fatal(err)
229                         }
230
231                         _, err = io.Copy(dst, src)
232                         if closeErr := dst.Close(); err == nil {
233                                 err = closeErr
234                         }
235                         if err != nil {
236                                 log.Fatal(err)
237                         }
238                 }
239
240                 cmd := exec.Command(testGo, "env", "CGO_ENABLED")
241                 cmd.Stderr = new(strings.Builder)
242                 if out, err := cmd.Output(); err != nil {
243                         fmt.Fprintf(os.Stderr, "running testgo failed: %v\n%s", err, cmd.Stderr)
244                         os.Exit(2)
245                 } else {
246                         canCgo, err = strconv.ParseBool(strings.TrimSpace(string(out)))
247                         if err != nil {
248                                 fmt.Fprintf(os.Stderr, "can't parse go env CGO_ENABLED output: %v\n", strings.TrimSpace(string(out)))
249                         }
250                 }
251
252                 out, err := exec.Command(gotool, "env", "GOCACHE").CombinedOutput()
253                 if err != nil {
254                         fmt.Fprintf(os.Stderr, "could not find testing GOCACHE: %v\n%s", err, out)
255                         os.Exit(2)
256                 }
257                 testGOCACHE = strings.TrimSpace(string(out))
258
259                 canMSan = canCgo && sys.MSanSupported(runtime.GOOS, runtime.GOARCH)
260                 canASan = canCgo && sys.ASanSupported(runtime.GOOS, runtime.GOARCH)
261                 canRace = canCgo && sys.RaceDetectorSupported(runtime.GOOS, runtime.GOARCH)
262                 // The race detector doesn't work on Alpine Linux:
263                 // golang.org/issue/14481
264                 // gccgo does not support the race detector.
265                 if isAlpineLinux() || runtime.Compiler == "gccgo" {
266                         canRace = false
267                 }
268                 canFuzz = sys.FuzzSupported(runtime.GOOS, runtime.GOARCH)
269                 fuzzInstrumented = sys.FuzzInstrumented(runtime.GOOS, runtime.GOARCH)
270         }
271         // Don't let these environment variables confuse the test.
272         os.Setenv("GOENV", "off")
273         os.Unsetenv("GOFLAGS")
274         os.Unsetenv("GOBIN")
275         os.Unsetenv("GOPATH")
276         os.Unsetenv("GIT_ALLOW_PROTOCOL")
277         os.Setenv("HOME", "/test-go-home-does-not-exist")
278         // On some systems the default C compiler is ccache.
279         // Setting HOME to a non-existent directory will break
280         // those systems. Disable ccache and use real compiler. Issue 17668.
281         os.Setenv("CCACHE_DISABLE", "1")
282         if cfg.Getenv("GOCACHE") == "" {
283                 os.Setenv("GOCACHE", testGOCACHE) // because $HOME is gone
284         }
285
286         r := m.Run()
287         if !*testWork {
288                 removeAll(testTmpDir) // os.Exit won't run defer
289         }
290
291         if !*testWork {
292                 // There shouldn't be anything left in topTmpdir.
293                 dirf, err := os.Open(topTmpdir)
294                 if err != nil {
295                         log.Fatal(err)
296                 }
297                 names, err := dirf.Readdirnames(0)
298                 if err != nil {
299                         log.Fatal(err)
300                 }
301                 if len(names) > 0 {
302                         log.Fatalf("unexpected files left in tmpdir: %v", names)
303                 }
304
305                 removeAll(topTmpdir)
306         }
307
308         os.Exit(r)
309 }
310
311 func isAlpineLinux() bool {
312         if runtime.GOOS != "linux" {
313                 return false
314         }
315         fi, err := os.Lstat("/etc/alpine-release")
316         return err == nil && fi.Mode().IsRegular()
317 }
318
319 // The length of an mtime tick on this system. This is an estimate of
320 // how long we need to sleep to ensure that the mtime of two files is
321 // different.
322 // We used to try to be clever but that didn't always work (see golang.org/issue/12205).
323 var mtimeTick time.Duration = 1 * time.Second
324
325 // Manage a single run of the testgo binary.
326 type testgoData struct {
327         t              *testing.T
328         temps          []string
329         env            []string
330         tempdir        string
331         ran            bool
332         inParallel     bool
333         stdout, stderr bytes.Buffer
334         execDir        string // dir for tg.run
335 }
336
337 // skipIfGccgo skips the test if using gccgo.
338 func skipIfGccgo(t *testing.T, msg string) {
339         if runtime.Compiler == "gccgo" {
340                 t.Skipf("skipping test not supported on gccgo: %s", msg)
341         }
342 }
343
344 // testgo sets up for a test that runs testgo.
345 func testgo(t *testing.T) *testgoData {
346         t.Helper()
347         testenv.MustHaveGoBuild(t)
348         testenv.SkipIfShortAndSlow(t)
349
350         return &testgoData{t: t}
351 }
352
353 // must gives a fatal error if err is not nil.
354 func (tg *testgoData) must(err error) {
355         tg.t.Helper()
356         if err != nil {
357                 tg.t.Fatal(err)
358         }
359 }
360
361 // check gives a test non-fatal error if err is not nil.
362 func (tg *testgoData) check(err error) {
363         tg.t.Helper()
364         if err != nil {
365                 tg.t.Error(err)
366         }
367 }
368
369 // parallel runs the test in parallel by calling t.Parallel.
370 func (tg *testgoData) parallel() {
371         tg.t.Helper()
372         if tg.ran {
373                 tg.t.Fatal("internal testsuite error: call to parallel after run")
374         }
375         for _, e := range tg.env {
376                 if strings.HasPrefix(e, "GOROOT=") || strings.HasPrefix(e, "GOPATH=") || strings.HasPrefix(e, "GOBIN=") {
377                         val := e[strings.Index(e, "=")+1:]
378                         if strings.HasPrefix(val, "testdata") || strings.HasPrefix(val, "./testdata") {
379                                 tg.t.Fatalf("internal testsuite error: call to parallel with testdata in environment (%s)", e)
380                         }
381                 }
382         }
383         tg.inParallel = true
384         tg.t.Parallel()
385 }
386
387 // pwd returns the current directory.
388 func (tg *testgoData) pwd() string {
389         tg.t.Helper()
390         wd, err := os.Getwd()
391         if err != nil {
392                 tg.t.Fatalf("could not get working directory: %v", err)
393         }
394         return wd
395 }
396
397 // sleep sleeps for one tick, where a tick is a conservative estimate
398 // of how long it takes for a file modification to get a different
399 // mtime.
400 func (tg *testgoData) sleep() {
401         time.Sleep(mtimeTick)
402 }
403
404 // setenv sets an environment variable to use when running the test go
405 // command.
406 func (tg *testgoData) setenv(name, val string) {
407         tg.t.Helper()
408         if tg.inParallel && (name == "GOROOT" || name == "GOPATH" || name == "GOBIN") && (strings.HasPrefix(val, "testdata") || strings.HasPrefix(val, "./testdata")) {
409                 tg.t.Fatalf("internal testsuite error: call to setenv with testdata (%s=%s) after parallel", name, val)
410         }
411         tg.unsetenv(name)
412         tg.env = append(tg.env, name+"="+val)
413 }
414
415 // unsetenv removes an environment variable.
416 func (tg *testgoData) unsetenv(name string) {
417         if tg.env == nil {
418                 tg.env = append([]string(nil), os.Environ()...)
419                 tg.env = append(tg.env, "GO111MODULE=off")
420         }
421         for i, v := range tg.env {
422                 if strings.HasPrefix(v, name+"=") {
423                         tg.env = append(tg.env[:i], tg.env[i+1:]...)
424                         break
425                 }
426         }
427 }
428
429 func (tg *testgoData) goTool() string {
430         return testGo
431 }
432
433 // doRun runs the test go command, recording stdout and stderr and
434 // returning exit status.
435 func (tg *testgoData) doRun(args []string) error {
436         tg.t.Helper()
437         if tg.inParallel {
438                 for _, arg := range args {
439                         if strings.HasPrefix(arg, "testdata") || strings.HasPrefix(arg, "./testdata") {
440                                 tg.t.Fatal("internal testsuite error: parallel run using testdata")
441                         }
442                 }
443         }
444
445         hasGoroot := false
446         for _, v := range tg.env {
447                 if strings.HasPrefix(v, "GOROOT=") {
448                         hasGoroot = true
449                         break
450                 }
451         }
452         prog := tg.goTool()
453         if !hasGoroot {
454                 tg.setenv("GOROOT", testGOROOT)
455         }
456
457         tg.t.Logf("running testgo %v", args)
458         cmd := exec.Command(prog, args...)
459         tg.stdout.Reset()
460         tg.stderr.Reset()
461         cmd.Dir = tg.execDir
462         cmd.Stdout = &tg.stdout
463         cmd.Stderr = &tg.stderr
464         cmd.Env = tg.env
465         status := cmd.Run()
466         if tg.stdout.Len() > 0 {
467                 tg.t.Log("standard output:")
468                 tg.t.Log(tg.stdout.String())
469         }
470         if tg.stderr.Len() > 0 {
471                 tg.t.Log("standard error:")
472                 tg.t.Log(tg.stderr.String())
473         }
474         tg.ran = true
475         return status
476 }
477
478 // run runs the test go command, and expects it to succeed.
479 func (tg *testgoData) run(args ...string) {
480         tg.t.Helper()
481         if status := tg.doRun(args); status != nil {
482                 wd, _ := os.Getwd()
483                 tg.t.Logf("go %v failed unexpectedly in %s: %v", args, wd, status)
484                 tg.t.FailNow()
485         }
486 }
487
488 // runFail runs the test go command, and expects it to fail.
489 func (tg *testgoData) runFail(args ...string) {
490         tg.t.Helper()
491         if status := tg.doRun(args); status == nil {
492                 tg.t.Fatal("testgo succeeded unexpectedly")
493         } else {
494                 tg.t.Log("testgo failed as expected:", status)
495         }
496 }
497
498 // runGit runs a git command, and expects it to succeed.
499 func (tg *testgoData) runGit(dir string, args ...string) {
500         tg.t.Helper()
501         cmd := exec.Command("git", args...)
502         tg.stdout.Reset()
503         tg.stderr.Reset()
504         cmd.Stdout = &tg.stdout
505         cmd.Stderr = &tg.stderr
506         cmd.Dir = dir
507         cmd.Env = tg.env
508         status := cmd.Run()
509         if tg.stdout.Len() > 0 {
510                 tg.t.Log("git standard output:")
511                 tg.t.Log(tg.stdout.String())
512         }
513         if tg.stderr.Len() > 0 {
514                 tg.t.Log("git standard error:")
515                 tg.t.Log(tg.stderr.String())
516         }
517         if status != nil {
518                 tg.t.Logf("git %v failed unexpectedly: %v", args, status)
519                 tg.t.FailNow()
520         }
521 }
522
523 // getStdout returns standard output of the testgo run as a string.
524 func (tg *testgoData) getStdout() string {
525         tg.t.Helper()
526         if !tg.ran {
527                 tg.t.Fatal("internal testsuite error: stdout called before run")
528         }
529         return tg.stdout.String()
530 }
531
532 // getStderr returns standard error of the testgo run as a string.
533 func (tg *testgoData) getStderr() string {
534         tg.t.Helper()
535         if !tg.ran {
536                 tg.t.Fatal("internal testsuite error: stdout called before run")
537         }
538         return tg.stderr.String()
539 }
540
541 // doGrepMatch looks for a regular expression in a buffer, and returns
542 // whether it is found. The regular expression is matched against
543 // each line separately, as with the grep command.
544 func (tg *testgoData) doGrepMatch(match string, b *bytes.Buffer) bool {
545         tg.t.Helper()
546         if !tg.ran {
547                 tg.t.Fatal("internal testsuite error: grep called before run")
548         }
549         re := regexp.MustCompile(match)
550         for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) {
551                 if re.Match(ln) {
552                         return true
553                 }
554         }
555         return false
556 }
557
558 // doGrep looks for a regular expression in a buffer and fails if it
559 // is not found. The name argument is the name of the output we are
560 // searching, "output" or "error". The msg argument is logged on
561 // failure.
562 func (tg *testgoData) doGrep(match string, b *bytes.Buffer, name, msg string) {
563         tg.t.Helper()
564         if !tg.doGrepMatch(match, b) {
565                 tg.t.Log(msg)
566                 tg.t.Logf("pattern %v not found in standard %s", match, name)
567                 tg.t.FailNow()
568         }
569 }
570
571 // grepStdout looks for a regular expression in the test run's
572 // standard output and fails, logging msg, if it is not found.
573 func (tg *testgoData) grepStdout(match, msg string) {
574         tg.t.Helper()
575         tg.doGrep(match, &tg.stdout, "output", msg)
576 }
577
578 // grepStderr looks for a regular expression in the test run's
579 // standard error and fails, logging msg, if it is not found.
580 func (tg *testgoData) grepStderr(match, msg string) {
581         tg.t.Helper()
582         tg.doGrep(match, &tg.stderr, "error", msg)
583 }
584
585 // grepBoth looks for a regular expression in the test run's standard
586 // output or stand error and fails, logging msg, if it is not found.
587 func (tg *testgoData) grepBoth(match, msg string) {
588         tg.t.Helper()
589         if !tg.doGrepMatch(match, &tg.stdout) && !tg.doGrepMatch(match, &tg.stderr) {
590                 tg.t.Log(msg)
591                 tg.t.Logf("pattern %v not found in standard output or standard error", match)
592                 tg.t.FailNow()
593         }
594 }
595
596 // doGrepNot looks for a regular expression in a buffer and fails if
597 // it is found. The name and msg arguments are as for doGrep.
598 func (tg *testgoData) doGrepNot(match string, b *bytes.Buffer, name, msg string) {
599         tg.t.Helper()
600         if tg.doGrepMatch(match, b) {
601                 tg.t.Log(msg)
602                 tg.t.Logf("pattern %v found unexpectedly in standard %s", match, name)
603                 tg.t.FailNow()
604         }
605 }
606
607 // grepStdoutNot looks for a regular expression in the test run's
608 // standard output and fails, logging msg, if it is found.
609 func (tg *testgoData) grepStdoutNot(match, msg string) {
610         tg.t.Helper()
611         tg.doGrepNot(match, &tg.stdout, "output", msg)
612 }
613
614 // grepStderrNot looks for a regular expression in the test run's
615 // standard error and fails, logging msg, if it is found.
616 func (tg *testgoData) grepStderrNot(match, msg string) {
617         tg.t.Helper()
618         tg.doGrepNot(match, &tg.stderr, "error", msg)
619 }
620
621 // grepBothNot looks for a regular expression in the test run's
622 // standard output or standard error and fails, logging msg, if it is
623 // found.
624 func (tg *testgoData) grepBothNot(match, msg string) {
625         tg.t.Helper()
626         if tg.doGrepMatch(match, &tg.stdout) || tg.doGrepMatch(match, &tg.stderr) {
627                 tg.t.Log(msg)
628                 tg.t.Fatalf("pattern %v found unexpectedly in standard output or standard error", match)
629         }
630 }
631
632 // doGrepCount counts the number of times a regexp is seen in a buffer.
633 func (tg *testgoData) doGrepCount(match string, b *bytes.Buffer) int {
634         tg.t.Helper()
635         if !tg.ran {
636                 tg.t.Fatal("internal testsuite error: doGrepCount called before run")
637         }
638         re := regexp.MustCompile(match)
639         c := 0
640         for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) {
641                 if re.Match(ln) {
642                         c++
643                 }
644         }
645         return c
646 }
647
648 // grepCountBoth returns the number of times a regexp is seen in both
649 // standard output and standard error.
650 func (tg *testgoData) grepCountBoth(match string) int {
651         tg.t.Helper()
652         return tg.doGrepCount(match, &tg.stdout) + tg.doGrepCount(match, &tg.stderr)
653 }
654
655 // creatingTemp records that the test plans to create a temporary file
656 // or directory. If the file or directory exists already, it will be
657 // removed. When the test completes, the file or directory will be
658 // removed if it exists.
659 func (tg *testgoData) creatingTemp(path string) {
660         tg.t.Helper()
661         if filepath.IsAbs(path) && !strings.HasPrefix(path, tg.tempdir) {
662                 tg.t.Fatalf("internal testsuite error: creatingTemp(%q) with absolute path not in temporary directory", path)
663         }
664         tg.must(robustio.RemoveAll(path))
665         tg.temps = append(tg.temps, path)
666 }
667
668 // makeTempdir makes a temporary directory for a run of testgo. If
669 // the temporary directory was already created, this does nothing.
670 func (tg *testgoData) makeTempdir() {
671         tg.t.Helper()
672         if tg.tempdir == "" {
673                 var err error
674                 tg.tempdir, err = os.MkdirTemp("", "gotest")
675                 tg.must(err)
676         }
677 }
678
679 // tempFile adds a temporary file for a run of testgo.
680 func (tg *testgoData) tempFile(path, contents string) {
681         tg.t.Helper()
682         tg.makeTempdir()
683         tg.must(os.MkdirAll(filepath.Join(tg.tempdir, filepath.Dir(path)), 0755))
684         bytes := []byte(contents)
685         if strings.HasSuffix(path, ".go") {
686                 formatted, err := format.Source(bytes)
687                 if err == nil {
688                         bytes = formatted
689                 }
690         }
691         tg.must(os.WriteFile(filepath.Join(tg.tempdir, path), bytes, 0644))
692 }
693
694 // tempDir adds a temporary directory for a run of testgo.
695 func (tg *testgoData) tempDir(path string) {
696         tg.t.Helper()
697         tg.makeTempdir()
698         if err := os.MkdirAll(filepath.Join(tg.tempdir, path), 0755); err != nil && !os.IsExist(err) {
699                 tg.t.Fatal(err)
700         }
701 }
702
703 // path returns the absolute pathname to file with the temporary
704 // directory.
705 func (tg *testgoData) path(name string) string {
706         tg.t.Helper()
707         if tg.tempdir == "" {
708                 tg.t.Fatalf("internal testsuite error: path(%q) with no tempdir", name)
709         }
710         if name == "." {
711                 return tg.tempdir
712         }
713         return filepath.Join(tg.tempdir, name)
714 }
715
716 // mustExist fails if path does not exist.
717 func (tg *testgoData) mustExist(path string) {
718         tg.t.Helper()
719         if _, err := os.Stat(path); err != nil {
720                 if os.IsNotExist(err) {
721                         tg.t.Fatalf("%s does not exist but should", path)
722                 }
723                 tg.t.Fatalf("%s stat failed: %v", path, err)
724         }
725 }
726
727 // mustNotExist fails if path exists.
728 func (tg *testgoData) mustNotExist(path string) {
729         tg.t.Helper()
730         if _, err := os.Stat(path); err == nil || !os.IsNotExist(err) {
731                 tg.t.Fatalf("%s exists but should not (%v)", path, err)
732         }
733 }
734
735 // mustHaveContent succeeds if filePath is a path to a file,
736 // and that file is readable and not empty.
737 func (tg *testgoData) mustHaveContent(filePath string) {
738         tg.mustExist(filePath)
739         f, err := os.Stat(filePath)
740         if err != nil {
741                 tg.t.Fatal(err)
742         }
743         if f.Size() == 0 {
744                 tg.t.Fatalf("expected %s to have data, but is empty", filePath)
745         }
746 }
747
748 // wantExecutable fails with msg if path is not executable.
749 func (tg *testgoData) wantExecutable(path, msg string) {
750         tg.t.Helper()
751         if st, err := os.Stat(path); err != nil {
752                 if !os.IsNotExist(err) {
753                         tg.t.Log(err)
754                 }
755                 tg.t.Fatal(msg)
756         } else {
757                 if runtime.GOOS != "windows" && st.Mode()&0111 == 0 {
758                         tg.t.Fatalf("binary %s exists but is not executable", path)
759                 }
760         }
761 }
762
763 // isStale reports whether pkg is stale, and why
764 func (tg *testgoData) isStale(pkg string) (bool, string) {
765         tg.t.Helper()
766         tg.run("list", "-f", "{{.Stale}}:{{.StaleReason}}", pkg)
767         v := strings.TrimSpace(tg.getStdout())
768         f := strings.SplitN(v, ":", 2)
769         if len(f) == 2 {
770                 switch f[0] {
771                 case "true":
772                         return true, f[1]
773                 case "false":
774                         return false, f[1]
775                 }
776         }
777         tg.t.Fatalf("unexpected output checking staleness of package %v: %v", pkg, v)
778         panic("unreachable")
779 }
780
781 // wantStale fails with msg if pkg is not stale.
782 func (tg *testgoData) wantStale(pkg, reason, msg string) {
783         tg.t.Helper()
784         stale, why := tg.isStale(pkg)
785         if !stale {
786                 tg.t.Fatal(msg)
787         }
788         // We always accept the reason as being "not installed but
789         // available in build cache", because when that is the case go
790         // list doesn't try to sort out the underlying reason why the
791         // package is not installed.
792         if reason == "" && why != "" || !strings.Contains(why, reason) && !strings.Contains(why, "not installed but available in build cache") {
793                 tg.t.Errorf("wrong reason for Stale=true: %q, want %q", why, reason)
794         }
795 }
796
797 // wantNotStale fails with msg if pkg is stale.
798 func (tg *testgoData) wantNotStale(pkg, reason, msg string) {
799         tg.t.Helper()
800         stale, why := tg.isStale(pkg)
801         if stale {
802                 tg.t.Fatal(msg)
803         }
804         if reason == "" && why != "" || !strings.Contains(why, reason) {
805                 tg.t.Errorf("wrong reason for Stale=false: %q, want %q", why, reason)
806         }
807 }
808
809 // If -testwork is specified, the test prints the name of the temp directory
810 // and does not remove it when done, so that a programmer can
811 // poke at the test file tree afterward.
812 var testWork = flag.Bool("testwork", false, "")
813
814 // cleanup cleans up a test that runs testgo.
815 func (tg *testgoData) cleanup() {
816         tg.t.Helper()
817         if *testWork {
818                 tg.t.Logf("TESTWORK=%s\n", tg.path("."))
819                 return
820         }
821         for _, path := range tg.temps {
822                 tg.check(removeAll(path))
823         }
824         if tg.tempdir != "" {
825                 tg.check(removeAll(tg.tempdir))
826         }
827 }
828
829 func removeAll(dir string) error {
830         // module cache has 0444 directories;
831         // make them writable in order to remove content.
832         filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error {
833                 // chmod not only directories, but also things that we couldn't even stat
834                 // due to permission errors: they may also be unreadable directories.
835                 if err != nil || info.IsDir() {
836                         os.Chmod(path, 0777)
837                 }
838                 return nil
839         })
840         return robustio.RemoveAll(dir)
841 }
842
843 // failSSH puts an ssh executable in the PATH that always fails.
844 // This is to stub out uses of ssh by go get.
845 func (tg *testgoData) failSSH() {
846         tg.t.Helper()
847         wd, err := os.Getwd()
848         if err != nil {
849                 tg.t.Fatal(err)
850         }
851         fail := filepath.Join(wd, "testdata/failssh")
852         tg.setenv("PATH", fmt.Sprintf("%v%c%v", fail, filepath.ListSeparator, os.Getenv("PATH")))
853 }
854
855 func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
856         if testing.Short() {
857                 t.Skip("skipping lengthy test in short mode")
858         }
859
860         tg := testgo(t)
861         defer tg.cleanup()
862         tg.parallel()
863
864         // Copy the runtime packages into a temporary GOROOT
865         // so that we can change files.
866         for _, copydir := range []string{
867                 "src/runtime",
868                 "src/internal/abi",
869                 "src/internal/bytealg",
870                 "src/internal/cpu",
871                 "src/internal/goarch",
872                 "src/internal/goexperiment",
873                 "src/internal/goos",
874                 "src/math/bits",
875                 "src/unsafe",
876                 filepath.Join("pkg", runtime.GOOS+"_"+runtime.GOARCH),
877                 filepath.Join("pkg/tool", runtime.GOOS+"_"+runtime.GOARCH),
878                 "pkg/include",
879         } {
880                 srcdir := filepath.Join(testGOROOT, copydir)
881                 tg.tempDir(filepath.Join("goroot", copydir))
882                 err := filepath.WalkDir(srcdir,
883                         func(path string, info fs.DirEntry, err error) error {
884                                 if err != nil {
885                                         return err
886                                 }
887                                 if info.IsDir() {
888                                         return nil
889                                 }
890                                 srcrel, err := filepath.Rel(srcdir, path)
891                                 if err != nil {
892                                         return err
893                                 }
894                                 dest := filepath.Join("goroot", copydir, srcrel)
895                                 data, err := os.ReadFile(path)
896                                 if err != nil {
897                                         return err
898                                 }
899                                 tg.tempFile(dest, string(data))
900                                 if strings.Contains(copydir, filepath.Join("pkg", "tool")) {
901                                         os.Chmod(tg.path(dest), 0777)
902                                 }
903                                 return nil
904                         })
905                 if err != nil {
906                         t.Fatal(err)
907                 }
908         }
909         tg.setenv("GOROOT", tg.path("goroot"))
910
911         addVar := func(name string, idx int) (restore func()) {
912                 data, err := os.ReadFile(name)
913                 if err != nil {
914                         t.Fatal(err)
915                 }
916                 old := data
917                 data = append(data, fmt.Sprintf("var DummyUnusedVar%d bool\n", idx)...)
918                 if err := os.WriteFile(name, append(data, '\n'), 0666); err != nil {
919                         t.Fatal(err)
920                 }
921                 tg.sleep()
922                 return func() {
923                         if err := os.WriteFile(name, old, 0666); err != nil {
924                                 t.Fatal(err)
925                         }
926                 }
927         }
928
929         // Every main package depends on the "runtime".
930         tg.tempFile("d1/src/p1/p1.go", `package main; func main(){}`)
931         tg.setenv("GOPATH", tg.path("d1"))
932         // Pass -i flag to rebuild everything outdated.
933         tg.run("install", "-i", "p1")
934         tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, before any changes")
935
936         // Changing mtime of runtime/internal/sys/sys.go
937         // should have no effect: only the content matters.
938         // In fact this should be true even outside a release branch.
939         sys := tg.path("goroot/src/runtime/internal/sys/sys.go")
940         tg.sleep()
941         restore := addVar(sys, 0)
942         restore()
943         tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after updating mtime of runtime/internal/sys/sys.go")
944
945         // But changing content of any file should have an effect.
946         // Previously zversion.go was the only one that mattered;
947         // now they all matter, so keep using sys.go.
948         restore = addVar(sys, 1)
949         defer restore()
950         tg.wantStale("p1", "stale dependency: runtime/internal/sys", "./testgo list claims p1 is NOT stale, incorrectly, after changing sys.go")
951         restore()
952         tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after changing back to old release")
953         addVar(sys, 2)
954         tg.wantStale("p1", "stale dependency: runtime", "./testgo list claims p1 is NOT stale, incorrectly, after changing sys.go again")
955         tg.run("install", "-i", "p1")
956         tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with new release")
957
958         // Restore to "old" release.
959         restore()
960         tg.wantStale("p1", "stale dependency: runtime/internal/sys", "./testgo list claims p1 is NOT stale, incorrectly, after restoring sys.go")
961         tg.run("install", "-i", "p1")
962         tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with old release")
963 }
964
965 // cmd/go: custom import path checking should not apply to Go packages without import comment.
966 func TestIssue10952(t *testing.T) {
967         testenv.MustHaveExternalNetwork(t)
968         testenv.MustHaveExecPath(t, "git")
969
970         tg := testgo(t)
971         defer tg.cleanup()
972         tg.parallel()
973         tg.tempDir("src")
974         tg.setenv("GOPATH", tg.path("."))
975         const importPath = "github.com/zombiezen/go-get-issue-10952"
976         tg.run("get", "-d", "-u", importPath)
977         repoDir := tg.path("src/" + importPath)
978         tg.runGit(repoDir, "remote", "set-url", "origin", "https://"+importPath+".git")
979         tg.run("get", "-d", "-u", importPath)
980 }
981
982 func TestIssue16471(t *testing.T) {
983         testenv.MustHaveExternalNetwork(t)
984         testenv.MustHaveExecPath(t, "git")
985
986         tg := testgo(t)
987         defer tg.cleanup()
988         tg.parallel()
989         tg.tempDir("src")
990         tg.setenv("GOPATH", tg.path("."))
991         tg.must(os.MkdirAll(tg.path("src/rsc.io/go-get-issue-10952"), 0755))
992         tg.runGit(tg.path("src/rsc.io"), "clone", "https://github.com/zombiezen/go-get-issue-10952")
993         tg.runFail("get", "-u", "rsc.io/go-get-issue-10952")
994         tg.grepStderr("rsc.io/go-get-issue-10952 is a custom import path for https://github.com/rsc/go-get-issue-10952, but .* is checked out from https://github.com/zombiezen/go-get-issue-10952", "did not detect updated import path")
995 }
996
997 // Test git clone URL that uses SCP-like syntax and custom import path checking.
998 func TestIssue11457(t *testing.T) {
999         testenv.MustHaveExternalNetwork(t)
1000         testenv.MustHaveExecPath(t, "git")
1001
1002         tg := testgo(t)
1003         defer tg.cleanup()
1004         tg.parallel()
1005         tg.tempDir("src")
1006         tg.setenv("GOPATH", tg.path("."))
1007         const importPath = "rsc.io/go-get-issue-11457"
1008         tg.run("get", "-d", "-u", importPath)
1009         repoDir := tg.path("src/" + importPath)
1010         tg.runGit(repoDir, "remote", "set-url", "origin", "git@github.com:rsc/go-get-issue-11457")
1011
1012         // At this time, custom import path checking compares remotes verbatim (rather than
1013         // just the host and path, skipping scheme and user), so we expect go get -u to fail.
1014         // However, the goal of this test is to verify that gitRemoteRepo correctly parsed
1015         // the SCP-like syntax, and we expect it to appear in the error message.
1016         tg.runFail("get", "-d", "-u", importPath)
1017         want := " is checked out from ssh://git@github.com/rsc/go-get-issue-11457"
1018         if !strings.HasSuffix(strings.TrimSpace(tg.getStderr()), want) {
1019                 t.Error("expected clone URL to appear in stderr")
1020         }
1021 }
1022
1023 func TestGetGitDefaultBranch(t *testing.T) {
1024         testenv.MustHaveExternalNetwork(t)
1025         testenv.MustHaveExecPath(t, "git")
1026
1027         tg := testgo(t)
1028         defer tg.cleanup()
1029         tg.parallel()
1030         tg.tempDir("src")
1031         tg.setenv("GOPATH", tg.path("."))
1032
1033         // This repo has two branches, master and another-branch.
1034         // The another-branch is the default that you get from 'git clone'.
1035         // The go get command variants should not override this.
1036         const importPath = "github.com/rsc/go-get-default-branch"
1037
1038         tg.run("get", "-d", importPath)
1039         repoDir := tg.path("src/" + importPath)
1040         tg.runGit(repoDir, "branch", "--contains", "HEAD")
1041         tg.grepStdout(`\* another-branch`, "not on correct default branch")
1042
1043         tg.run("get", "-d", "-u", importPath)
1044         tg.runGit(repoDir, "branch", "--contains", "HEAD")
1045         tg.grepStdout(`\* another-branch`, "not on correct default branch")
1046 }
1047
1048 // Security issue. Don't disable. See golang.org/issue/22125.
1049 func TestAccidentalGitCheckout(t *testing.T) {
1050         testenv.MustHaveExternalNetwork(t)
1051         testenv.MustHaveExecPath(t, "git")
1052         testenv.MustHaveExecPath(t, "svn")
1053
1054         tg := testgo(t)
1055         defer tg.cleanup()
1056         tg.parallel()
1057         tg.tempDir("src")
1058
1059         tg.setenv("GOPATH", tg.path("."))
1060
1061         tg.runFail("get", "-u", "vcs-test.golang.org/go/test1-svn-git")
1062         tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason")
1063
1064         if _, err := os.Stat(tg.path("SrC")); err == nil {
1065                 // This case only triggers on a case-insensitive file system.
1066                 tg.runFail("get", "-u", "vcs-test.golang.org/go/test2-svn-git/test2main")
1067                 tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason")
1068         }
1069 }
1070
1071 func TestPackageMainTestCompilerFlags(t *testing.T) {
1072         tg := testgo(t)
1073         defer tg.cleanup()
1074         tg.parallel()
1075         tg.makeTempdir()
1076         tg.setenv("GOPATH", tg.path("."))
1077         tg.tempFile("src/p1/p1.go", "package main\n")
1078         tg.tempFile("src/p1/p1_test.go", "package main\nimport \"testing\"\nfunc Test(t *testing.T){}\n")
1079         tg.run("test", "-c", "-n", "p1")
1080         tg.grepBothNot(`([\\/]compile|gccgo).* (-p main|-fgo-pkgpath=main).*p1\.go`, "should not have run compile -p main p1.go")
1081         tg.grepStderr(`([\\/]compile|gccgo).* (-p p1|-fgo-pkgpath=p1).*p1\.go`, "should have run compile -p p1 p1.go")
1082 }
1083
1084 // Issue 4104.
1085 func TestGoTestWithPackageListedMultipleTimes(t *testing.T) {
1086         tooSlow(t)
1087         tg := testgo(t)
1088         defer tg.cleanup()
1089         tg.parallel()
1090         tg.run("test", "errors", "errors", "errors", "errors", "errors")
1091         if strings.Contains(strings.TrimSpace(tg.getStdout()), "\n") {
1092                 t.Error("go test errors errors errors errors errors tested the same package multiple times")
1093         }
1094 }
1095
1096 func TestGoListHasAConsistentOrder(t *testing.T) {
1097         tooSlow(t)
1098         tg := testgo(t)
1099         defer tg.cleanup()
1100         tg.parallel()
1101         tg.run("list", "std")
1102         first := tg.getStdout()
1103         tg.run("list", "std")
1104         if first != tg.getStdout() {
1105                 t.Error("go list std ordering is inconsistent")
1106         }
1107 }
1108
1109 func TestGoListStdDoesNotIncludeCommands(t *testing.T) {
1110         tooSlow(t)
1111         tg := testgo(t)
1112         defer tg.cleanup()
1113         tg.parallel()
1114         tg.run("list", "std")
1115         tg.grepStdoutNot("cmd/", "go list std shows commands")
1116 }
1117
1118 func TestGoListCmdOnlyShowsCommands(t *testing.T) {
1119         skipIfGccgo(t, "gccgo does not have GOROOT")
1120         tooSlow(t)
1121         tg := testgo(t)
1122         defer tg.cleanup()
1123         tg.parallel()
1124         tg.run("list", "cmd")
1125         out := strings.TrimSpace(tg.getStdout())
1126         for _, line := range strings.Split(out, "\n") {
1127                 if !strings.Contains(line, "cmd/") {
1128                         t.Error("go list cmd shows non-commands")
1129                         break
1130                 }
1131         }
1132 }
1133
1134 func TestGoListDeps(t *testing.T) {
1135         tg := testgo(t)
1136         defer tg.cleanup()
1137         tg.parallel()
1138         tg.tempDir("src/p1/p2/p3/p4")
1139         tg.setenv("GOPATH", tg.path("."))
1140         tg.tempFile("src/p1/p.go", "package p1\nimport _ \"p1/p2\"\n")
1141         tg.tempFile("src/p1/p2/p.go", "package p2\nimport _ \"p1/p2/p3\"\n")
1142         tg.tempFile("src/p1/p2/p3/p.go", "package p3\nimport _ \"p1/p2/p3/p4\"\n")
1143         tg.tempFile("src/p1/p2/p3/p4/p.go", "package p4\n")
1144         tg.run("list", "-f", "{{.Deps}}", "p1")
1145         tg.grepStdout("p1/p2/p3/p4", "Deps(p1) does not mention p4")
1146
1147         tg.run("list", "-deps", "p1")
1148         tg.grepStdout("p1/p2/p3/p4", "-deps p1 does not mention p4")
1149
1150         if runtime.Compiler != "gccgo" {
1151                 // Check the list is in dependency order.
1152                 tg.run("list", "-deps", "math")
1153                 want := "internal/cpu\nunsafe\nmath/bits\nmath\n"
1154                 out := tg.stdout.String()
1155                 if !strings.Contains(out, "internal/cpu") {
1156                         // Some systems don't use internal/cpu.
1157                         want = "unsafe\nmath/bits\nmath\n"
1158                 }
1159                 if tg.stdout.String() != want {
1160                         t.Fatalf("list -deps math: wrong order\nhave %q\nwant %q", tg.stdout.String(), want)
1161                 }
1162         }
1163 }
1164
1165 func TestGoListTest(t *testing.T) {
1166         skipIfGccgo(t, "gccgo does not have standard packages")
1167         tg := testgo(t)
1168         defer tg.cleanup()
1169         tg.parallel()
1170         tg.makeTempdir()
1171         tg.setenv("GOCACHE", tg.tempdir)
1172
1173         tg.run("list", "-test", "-deps", "sort")
1174         tg.grepStdout(`^sort.test$`, "missing test main")
1175         tg.grepStdout(`^sort$`, "missing real sort")
1176         tg.grepStdout(`^sort \[sort.test\]$`, "missing test copy of sort")
1177         tg.grepStdout(`^testing \[sort.test\]$`, "missing test copy of testing")
1178         tg.grepStdoutNot(`^testing$`, "unexpected real copy of testing")
1179
1180         tg.run("list", "-test", "sort")
1181         tg.grepStdout(`^sort.test$`, "missing test main")
1182         tg.grepStdout(`^sort$`, "missing real sort")
1183         tg.grepStdout(`^sort \[sort.test\]$`, "unexpected test copy of sort")
1184         tg.grepStdoutNot(`^testing \[sort.test\]$`, "unexpected test copy of testing")
1185         tg.grepStdoutNot(`^testing$`, "unexpected real copy of testing")
1186
1187         tg.run("list", "-test", "cmd/buildid", "cmd/doc")
1188         tg.grepStdout(`^cmd/buildid$`, "missing cmd/buildid")
1189         tg.grepStdout(`^cmd/doc$`, "missing cmd/doc")
1190         tg.grepStdout(`^cmd/doc\.test$`, "missing cmd/doc test")
1191         tg.grepStdoutNot(`^cmd/buildid\.test$`, "unexpected cmd/buildid test")
1192         tg.grepStdoutNot(`^testing`, "unexpected testing")
1193
1194         tg.run("list", "-test", "runtime/cgo")
1195         tg.grepStdout(`^runtime/cgo$`, "missing runtime/cgo")
1196
1197         tg.run("list", "-deps", "-f", "{{if .DepOnly}}{{.ImportPath}}{{end}}", "sort")
1198         tg.grepStdout(`^internal/reflectlite$`, "missing internal/reflectlite")
1199         tg.grepStdoutNot(`^sort`, "unexpected sort")
1200 }
1201
1202 func TestGoListCompiledCgo(t *testing.T) {
1203         tooSlow(t)
1204         tg := testgo(t)
1205         defer tg.cleanup()
1206         tg.parallel()
1207         tg.makeTempdir()
1208         tg.setenv("GOCACHE", tg.tempdir)
1209
1210         tg.run("list", "-f", `{{join .CgoFiles "\n"}}`, "net")
1211         if tg.stdout.String() == "" {
1212                 t.Skip("net does not use cgo")
1213         }
1214         if strings.Contains(tg.stdout.String(), tg.tempdir) {
1215                 t.Fatalf(".CgoFiles unexpectedly mentioned cache %s", tg.tempdir)
1216         }
1217         tg.run("list", "-compiled", "-f", `{{.Dir}}{{"\n"}}{{join .CompiledGoFiles "\n"}}`, "net")
1218         if !strings.Contains(tg.stdout.String(), tg.tempdir) {
1219                 t.Fatalf(".CompiledGoFiles with -compiled did not mention cache %s", tg.tempdir)
1220         }
1221         dir := ""
1222         for _, file := range strings.Split(tg.stdout.String(), "\n") {
1223                 if file == "" {
1224                         continue
1225                 }
1226                 if dir == "" {
1227                         dir = file
1228                         continue
1229                 }
1230                 if !strings.Contains(file, "/") && !strings.Contains(file, `\`) {
1231                         file = filepath.Join(dir, file)
1232                 }
1233                 if _, err := os.Stat(file); err != nil {
1234                         t.Fatalf("cannot find .CompiledGoFiles result %s: %v", file, err)
1235                 }
1236         }
1237 }
1238
1239 func TestGoListExport(t *testing.T) {
1240         skipIfGccgo(t, "gccgo does not have standard packages")
1241         tg := testgo(t)
1242         defer tg.cleanup()
1243         tg.parallel()
1244         tg.makeTempdir()
1245         tg.setenv("GOCACHE", tg.tempdir)
1246
1247         tg.run("list", "-f", "{{.Export}}", "strings")
1248         if tg.stdout.String() != "" {
1249                 t.Fatalf(".Export without -export unexpectedly set")
1250         }
1251         tg.run("list", "-export", "-f", "{{.Export}}", "strings")
1252         file := strings.TrimSpace(tg.stdout.String())
1253         if file == "" {
1254                 t.Fatalf(".Export with -export was empty")
1255         }
1256         if _, err := os.Stat(file); err != nil {
1257                 t.Fatalf("cannot find .Export result %s: %v", file, err)
1258         }
1259
1260         tg.run("list", "-export", "-f", "{{.BuildID}}", "strings")
1261         buildID := strings.TrimSpace(tg.stdout.String())
1262         if buildID == "" {
1263                 t.Fatalf(".BuildID with -export was empty")
1264         }
1265
1266         tg.run("tool", "buildid", file)
1267         toolBuildID := strings.TrimSpace(tg.stdout.String())
1268         if buildID != toolBuildID {
1269                 t.Fatalf(".BuildID with -export %q disagrees with 'go tool buildid' %q", buildID, toolBuildID)
1270         }
1271 }
1272
1273 // Issue 4096. Validate the output of unsuccessful go install foo/quxx.
1274 func TestUnsuccessfulGoInstallShouldMentionMissingPackage(t *testing.T) {
1275         tg := testgo(t)
1276         defer tg.cleanup()
1277         tg.parallel()
1278         tg.runFail("install", "foo/quxx")
1279         if tg.grepCountBoth(`cannot find package "foo/quxx" in any of`) != 1 {
1280                 t.Error(`go install foo/quxx expected error: .*cannot find package "foo/quxx" in any of`)
1281         }
1282 }
1283
1284 func TestGOROOTSearchFailureReporting(t *testing.T) {
1285         tg := testgo(t)
1286         defer tg.cleanup()
1287         tg.parallel()
1288         tg.runFail("install", "foo/quxx")
1289         if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("foo", "quxx"))+` \(from \$GOROOT\)$`) != 1 {
1290                 t.Error(`go install foo/quxx expected error: .*foo/quxx (from $GOROOT)`)
1291         }
1292 }
1293
1294 func TestMultipleGOPATHEntriesReportedSeparately(t *testing.T) {
1295         tg := testgo(t)
1296         defer tg.cleanup()
1297         tg.parallel()
1298         sep := string(filepath.ListSeparator)
1299         tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
1300         tg.runFail("install", "foo/quxx")
1301         if tg.grepCountBoth(`testdata[/\\].[/\\]src[/\\]foo[/\\]quxx`) != 2 {
1302                 t.Error(`go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)\n.*testdata/b/src/foo/quxx`)
1303         }
1304 }
1305
1306 // Test (from $GOPATH) annotation is reported for the first GOPATH entry,
1307 func TestMentionGOPATHInFirstGOPATHEntry(t *testing.T) {
1308         tg := testgo(t)
1309         defer tg.cleanup()
1310         tg.parallel()
1311         sep := string(filepath.ListSeparator)
1312         tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
1313         tg.runFail("install", "foo/quxx")
1314         if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("testdata", "a", "src", "foo", "quxx"))+` \(from \$GOPATH\)$`) != 1 {
1315                 t.Error(`go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)`)
1316         }
1317 }
1318
1319 // but not on the second.
1320 func TestMentionGOPATHNotOnSecondEntry(t *testing.T) {
1321         tg := testgo(t)
1322         defer tg.cleanup()
1323         tg.parallel()
1324         sep := string(filepath.ListSeparator)
1325         tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
1326         tg.runFail("install", "foo/quxx")
1327         if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("testdata", "b", "src", "foo", "quxx"))+`$`) != 1 {
1328                 t.Error(`go install foo/quxx expected error: .*testdata/b/src/foo/quxx`)
1329         }
1330 }
1331
1332 func homeEnvName() string {
1333         switch runtime.GOOS {
1334         case "windows":
1335                 return "USERPROFILE"
1336         case "plan9":
1337                 return "home"
1338         default:
1339                 return "HOME"
1340         }
1341 }
1342
1343 func tempEnvName() string {
1344         switch runtime.GOOS {
1345         case "windows":
1346                 return "TMP"
1347         case "plan9":
1348                 return "TMPDIR" // actually plan 9 doesn't have one at all but this is fine
1349         default:
1350                 return "TMPDIR"
1351         }
1352 }
1353
1354 func TestDefaultGOPATH(t *testing.T) {
1355         tg := testgo(t)
1356         defer tg.cleanup()
1357         tg.parallel()
1358         tg.tempDir("home/go")
1359         tg.setenv(homeEnvName(), tg.path("home"))
1360
1361         tg.run("env", "GOPATH")
1362         tg.grepStdout(regexp.QuoteMeta(tg.path("home/go")), "want GOPATH=$HOME/go")
1363
1364         tg.setenv("GOROOT", tg.path("home/go"))
1365         tg.run("env", "GOPATH")
1366         tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go")
1367
1368         tg.setenv("GOROOT", tg.path("home/go")+"/")
1369         tg.run("env", "GOPATH")
1370         tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go/")
1371 }
1372
1373 func TestDefaultGOPATHGet(t *testing.T) {
1374         testenv.MustHaveExternalNetwork(t)
1375         testenv.MustHaveExecPath(t, "git")
1376
1377         tg := testgo(t)
1378         defer tg.cleanup()
1379         tg.parallel()
1380         tg.setenv("GOPATH", "")
1381         tg.tempDir("home")
1382         tg.setenv(homeEnvName(), tg.path("home"))
1383
1384         // warn for creating directory
1385         tg.run("get", "-v", "github.com/golang/example/hello")
1386         tg.grepStderr("created GOPATH="+regexp.QuoteMeta(tg.path("home/go"))+"; see 'go help gopath'", "did not create GOPATH")
1387
1388         // no warning if directory already exists
1389         tg.must(robustio.RemoveAll(tg.path("home/go")))
1390         tg.tempDir("home/go")
1391         tg.run("get", "github.com/golang/example/hello")
1392         tg.grepStderrNot(".", "expected no output on standard error")
1393
1394         // error if $HOME/go is a file
1395         tg.must(robustio.RemoveAll(tg.path("home/go")))
1396         tg.tempFile("home/go", "")
1397         tg.runFail("get", "github.com/golang/example/hello")
1398         tg.grepStderr(`mkdir .*[/\\]go: .*(not a directory|cannot find the path)`, "expected error because $HOME/go is a file")
1399 }
1400
1401 func TestDefaultGOPATHPrintedSearchList(t *testing.T) {
1402         tg := testgo(t)
1403         defer tg.cleanup()
1404         tg.parallel()
1405         tg.setenv("GOPATH", "")
1406         tg.tempDir("home")
1407         tg.setenv(homeEnvName(), tg.path("home"))
1408
1409         tg.runFail("install", "github.com/golang/example/hello")
1410         tg.grepStderr(regexp.QuoteMeta(tg.path("home/go/src/github.com/golang/example/hello"))+`.*from \$GOPATH`, "expected default GOPATH")
1411 }
1412
1413 func TestLdflagsArgumentsWithSpacesIssue3941(t *testing.T) {
1414         skipIfGccgo(t, "gccgo does not support -ldflags -X")
1415         tooSlow(t)
1416         tg := testgo(t)
1417         defer tg.cleanup()
1418         tg.parallel()
1419         tg.tempFile("main.go", `package main
1420                 var extern string
1421                 func main() {
1422                         println(extern)
1423                 }`)
1424         tg.run("run", "-ldflags", `-X "main.extern=hello world"`, tg.path("main.go"))
1425         tg.grepStderr("^hello world", `ldflags -X "main.extern=hello world"' failed`)
1426 }
1427
1428 func TestLdFlagsLongArgumentsIssue42295(t *testing.T) {
1429         // Test the extremely long command line arguments that contain '\n' characters
1430         // get encoded and passed correctly.
1431         skipIfGccgo(t, "gccgo does not support -ldflags -X")
1432         tooSlow(t)
1433         tg := testgo(t)
1434         defer tg.cleanup()
1435         tg.parallel()
1436         tg.tempFile("main.go", `package main
1437                 var extern string
1438                 func main() {
1439                         print(extern)
1440                 }`)
1441         testStr := "test test test test test \n\\ "
1442         var buf bytes.Buffer
1443         for buf.Len() < sys.ExecArgLengthLimit+1 {
1444                 buf.WriteString(testStr)
1445         }
1446         tg.run("run", "-ldflags", fmt.Sprintf(`-X "main.extern=%s"`, buf.String()), tg.path("main.go"))
1447         if tg.stderr.String() != buf.String() {
1448                 t.Errorf("strings differ")
1449         }
1450 }
1451
1452 func TestGoTestDashCDashOControlsBinaryLocation(t *testing.T) {
1453         skipIfGccgo(t, "gccgo has no standard packages")
1454         tooSlow(t)
1455         tg := testgo(t)
1456         defer tg.cleanup()
1457         tg.parallel()
1458         tg.makeTempdir()
1459         tg.run("test", "-c", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
1460         tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -c -o myerrors.test did not create myerrors.test")
1461 }
1462
1463 func TestGoTestDashOWritesBinary(t *testing.T) {
1464         skipIfGccgo(t, "gccgo has no standard packages")
1465         tooSlow(t)
1466         tg := testgo(t)
1467         defer tg.cleanup()
1468         tg.parallel()
1469         tg.makeTempdir()
1470         tg.run("test", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
1471         tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -o myerrors.test did not create myerrors.test")
1472 }
1473
1474 func TestGoTestDashIDashOWritesBinary(t *testing.T) {
1475         skipIfGccgo(t, "gccgo has no standard packages")
1476         tooSlow(t)
1477         tg := testgo(t)
1478         defer tg.cleanup()
1479         tg.parallel()
1480         tg.makeTempdir()
1481
1482         // don't let test -i overwrite runtime
1483         tg.wantNotStale("runtime", "", "must be non-stale before test -i")
1484
1485         tg.run("test", "-v", "-i", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
1486         tg.grepBothNot("PASS|FAIL", "test should not have run")
1487         tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -o myerrors.test did not create myerrors.test")
1488 }
1489
1490 // Issue 4515.
1491 func TestInstallWithTags(t *testing.T) {
1492         tooSlow(t)
1493         tg := testgo(t)
1494         defer tg.cleanup()
1495         tg.parallel()
1496         tg.tempDir("bin")
1497         tg.tempFile("src/example/a/main.go", `package main
1498                 func main() {}`)
1499         tg.tempFile("src/example/b/main.go", `// +build mytag
1500
1501                 package main
1502                 func main() {}`)
1503         tg.setenv("GOPATH", tg.path("."))
1504         tg.run("install", "-tags", "mytag", "example/a", "example/b")
1505         tg.wantExecutable(tg.path("bin/a"+exeSuffix), "go install example/a example/b did not install binaries")
1506         tg.wantExecutable(tg.path("bin/b"+exeSuffix), "go install example/a example/b did not install binaries")
1507         tg.must(os.Remove(tg.path("bin/a" + exeSuffix)))
1508         tg.must(os.Remove(tg.path("bin/b" + exeSuffix)))
1509         tg.run("install", "-tags", "mytag", "example/...")
1510         tg.wantExecutable(tg.path("bin/a"+exeSuffix), "go install example/... did not install binaries")
1511         tg.wantExecutable(tg.path("bin/b"+exeSuffix), "go install example/... did not install binaries")
1512         tg.run("list", "-tags", "mytag", "example/b...")
1513         if strings.TrimSpace(tg.getStdout()) != "example/b" {
1514                 t.Error("go list example/b did not find example/b")
1515         }
1516 }
1517
1518 // Issue 17451, 17662.
1519 func TestSymlinkWarning(t *testing.T) {
1520         tg := testgo(t)
1521         defer tg.cleanup()
1522         tg.parallel()
1523         tg.makeTempdir()
1524         tg.setenv("GOPATH", tg.path("."))
1525
1526         tg.tempDir("src/example/xx")
1527         tg.tempDir("yy/zz")
1528         tg.tempFile("yy/zz/zz.go", "package zz\n")
1529         if err := os.Symlink(tg.path("yy"), tg.path("src/example/xx/yy")); err != nil {
1530                 t.Skipf("symlink failed: %v", err)
1531         }
1532         tg.run("list", "example/xx/z...")
1533         tg.grepStdoutNot(".", "list should not have matched anything")
1534         tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages")
1535         tg.grepStderrNot("symlink", "list should not have reported symlink")
1536
1537         tg.run("list", "example/xx/...")
1538         tg.grepStdoutNot(".", "list should not have matched anything")
1539         tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages")
1540         tg.grepStderr("ignoring symlink", "list should have reported symlink")
1541 }
1542
1543 func TestCgoShowsFullPathNames(t *testing.T) {
1544         if !canCgo {
1545                 t.Skip("skipping because cgo not enabled")
1546         }
1547
1548         tg := testgo(t)
1549         defer tg.cleanup()
1550         tg.parallel()
1551         tg.tempFile("src/x/y/dirname/foo.go", `
1552                 package foo
1553                 import "C"
1554                 func f() {`)
1555         tg.setenv("GOPATH", tg.path("."))
1556         tg.runFail("build", "x/y/dirname")
1557         tg.grepBoth("x/y/dirname", "error did not use full path")
1558 }
1559
1560 func TestCgoHandlesWlORIGIN(t *testing.T) {
1561         tooSlow(t)
1562         if !canCgo {
1563                 t.Skip("skipping because cgo not enabled")
1564         }
1565
1566         tg := testgo(t)
1567         defer tg.cleanup()
1568         tg.parallel()
1569         tg.tempFile("src/origin/origin.go", `package origin
1570                 // #cgo !darwin LDFLAGS: -Wl,-rpath,$ORIGIN
1571                 // void f(void) {}
1572                 import "C"
1573                 func f() { C.f() }`)
1574         tg.setenv("GOPATH", tg.path("."))
1575         tg.run("build", "origin")
1576 }
1577
1578 func TestCgoPkgConfig(t *testing.T) {
1579         tooSlow(t)
1580         if !canCgo {
1581                 t.Skip("skipping because cgo not enabled")
1582         }
1583         tg := testgo(t)
1584         defer tg.cleanup()
1585         tg.parallel()
1586
1587         tg.run("env", "PKG_CONFIG")
1588         pkgConfig := strings.TrimSpace(tg.getStdout())
1589         testenv.MustHaveExecPath(t, pkgConfig)
1590         if out, err := exec.Command(pkgConfig, "--atleast-pkgconfig-version", "0.24").CombinedOutput(); err != nil {
1591                 t.Skipf("%s --atleast-pkgconfig-version 0.24: %v\n%s", pkgConfig, err, out)
1592         }
1593
1594         // OpenBSD's pkg-config is strict about whitespace and only
1595         // supports backslash-escaped whitespace. It does not support
1596         // quotes, which the normal freedesktop.org pkg-config does
1597         // support. See https://man.openbsd.org/pkg-config.1
1598         tg.tempFile("foo.pc", `
1599 Name: foo
1600 Description: The foo library
1601 Version: 1.0.0
1602 Cflags: -Dhello=10 -Dworld=+32 -DDEFINED_FROM_PKG_CONFIG=hello\ world
1603 `)
1604         tg.tempFile("foo.go", `package main
1605
1606 /*
1607 #cgo pkg-config: foo
1608 int value() {
1609         return DEFINED_FROM_PKG_CONFIG;
1610 }
1611 */
1612 import "C"
1613 import "os"
1614
1615 func main() {
1616         if C.value() != 42 {
1617                 println("value() =", C.value(), "wanted 42")
1618                 os.Exit(1)
1619         }
1620 }
1621 `)
1622         tg.setenv("PKG_CONFIG_PATH", tg.path("."))
1623         tg.run("run", tg.path("foo.go"))
1624 }
1625
1626 func TestListTemplateContextFunction(t *testing.T) {
1627         t.Parallel()
1628         for _, tt := range []struct {
1629                 v    string
1630                 want string
1631         }{
1632                 {"GOARCH", runtime.GOARCH},
1633                 {"GOOS", runtime.GOOS},
1634                 {"GOROOT", testGOROOT},
1635                 {"GOPATH", os.Getenv("GOPATH")},
1636                 {"CgoEnabled", ""},
1637                 {"UseAllFiles", ""},
1638                 {"Compiler", ""},
1639                 {"BuildTags", ""},
1640                 {"ReleaseTags", ""},
1641                 {"InstallSuffix", ""},
1642         } {
1643                 tt := tt
1644                 t.Run(tt.v, func(t *testing.T) {
1645                         tg := testgo(t)
1646                         tg.parallel()
1647                         defer tg.cleanup()
1648                         tmpl := "{{context." + tt.v + "}}"
1649                         tg.run("list", "-f", tmpl)
1650                         if tt.want == "" {
1651                                 return
1652                         }
1653                         if got := strings.TrimSpace(tg.getStdout()); got != tt.want {
1654                                 t.Errorf("go list -f %q: got %q; want %q", tmpl, got, tt.want)
1655                         }
1656                 })
1657         }
1658 }
1659
1660 // Test that you cannot use a local import in a package
1661 // accessed by a non-local import (found in a GOPATH/GOROOT).
1662 // See golang.org/issue/17475.
1663 func TestImportLocal(t *testing.T) {
1664         tooSlow(t)
1665
1666         tg := testgo(t)
1667         tg.parallel()
1668         defer tg.cleanup()
1669
1670         tg.tempFile("src/dir/x/x.go", `package x
1671                 var X int
1672         `)
1673         tg.setenv("GOPATH", tg.path("."))
1674         tg.run("build", "dir/x")
1675
1676         // Ordinary import should work.
1677         tg.tempFile("src/dir/p0/p.go", `package p0
1678                 import "dir/x"
1679                 var _ = x.X
1680         `)
1681         tg.run("build", "dir/p0")
1682
1683         // Relative import should not.
1684         tg.tempFile("src/dir/p1/p.go", `package p1
1685                 import "../x"
1686                 var _ = x.X
1687         `)
1688         tg.runFail("build", "dir/p1")
1689         tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1690
1691         // ... even in a test.
1692         tg.tempFile("src/dir/p2/p.go", `package p2
1693         `)
1694         tg.tempFile("src/dir/p2/p_test.go", `package p2
1695                 import "../x"
1696                 import "testing"
1697                 var _ = x.X
1698                 func TestFoo(t *testing.T) {}
1699         `)
1700         tg.run("build", "dir/p2")
1701         tg.runFail("test", "dir/p2")
1702         tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1703
1704         // ... even in an xtest.
1705         tg.tempFile("src/dir/p2/p_test.go", `package p2_test
1706                 import "../x"
1707                 import "testing"
1708                 var _ = x.X
1709                 func TestFoo(t *testing.T) {}
1710         `)
1711         tg.run("build", "dir/p2")
1712         tg.runFail("test", "dir/p2")
1713         tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1714
1715         // Relative import starting with ./ should not work either.
1716         tg.tempFile("src/dir/d.go", `package dir
1717                 import "./x"
1718                 var _ = x.X
1719         `)
1720         tg.runFail("build", "dir")
1721         tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1722
1723         // ... even in a test.
1724         tg.tempFile("src/dir/d.go", `package dir
1725         `)
1726         tg.tempFile("src/dir/d_test.go", `package dir
1727                 import "./x"
1728                 import "testing"
1729                 var _ = x.X
1730                 func TestFoo(t *testing.T) {}
1731         `)
1732         tg.run("build", "dir")
1733         tg.runFail("test", "dir")
1734         tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1735
1736         // ... even in an xtest.
1737         tg.tempFile("src/dir/d_test.go", `package dir_test
1738                 import "./x"
1739                 import "testing"
1740                 var _ = x.X
1741                 func TestFoo(t *testing.T) {}
1742         `)
1743         tg.run("build", "dir")
1744         tg.runFail("test", "dir")
1745         tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1746
1747         // Relative import plain ".." should not work.
1748         tg.tempFile("src/dir/x/y/y.go", `package dir
1749                 import ".."
1750                 var _ = x.X
1751         `)
1752         tg.runFail("build", "dir/x/y")
1753         tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1754
1755         // ... even in a test.
1756         tg.tempFile("src/dir/x/y/y.go", `package y
1757         `)
1758         tg.tempFile("src/dir/x/y/y_test.go", `package y
1759                 import ".."
1760                 import "testing"
1761                 var _ = x.X
1762                 func TestFoo(t *testing.T) {}
1763         `)
1764         tg.run("build", "dir/x/y")
1765         tg.runFail("test", "dir/x/y")
1766         tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1767
1768         // ... even in an x test.
1769         tg.tempFile("src/dir/x/y/y_test.go", `package y_test
1770                 import ".."
1771                 import "testing"
1772                 var _ = x.X
1773                 func TestFoo(t *testing.T) {}
1774         `)
1775         tg.run("build", "dir/x/y")
1776         tg.runFail("test", "dir/x/y")
1777         tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1778
1779         // Relative import "." should not work.
1780         tg.tempFile("src/dir/x/xx.go", `package x
1781                 import "."
1782                 var _ = x.X
1783         `)
1784         tg.runFail("build", "dir/x")
1785         tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
1786
1787         // ... even in a test.
1788         tg.tempFile("src/dir/x/xx.go", `package x
1789         `)
1790         tg.tempFile("src/dir/x/xx_test.go", `package x
1791                 import "."
1792                 import "testing"
1793                 var _ = x.X
1794                 func TestFoo(t *testing.T) {}
1795         `)
1796         tg.run("build", "dir/x")
1797         tg.runFail("test", "dir/x")
1798         tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
1799
1800         // ... even in an xtest.
1801         tg.tempFile("src/dir/x/xx.go", `package x
1802         `)
1803         tg.tempFile("src/dir/x/xx_test.go", `package x_test
1804                 import "."
1805                 import "testing"
1806                 var _ = x.X
1807                 func TestFoo(t *testing.T) {}
1808         `)
1809         tg.run("build", "dir/x")
1810         tg.runFail("test", "dir/x")
1811         tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
1812 }
1813
1814 func TestGoInstallPkgdir(t *testing.T) {
1815         skipIfGccgo(t, "gccgo has no standard packages")
1816         tooSlow(t)
1817
1818         tg := testgo(t)
1819         tg.parallel()
1820         defer tg.cleanup()
1821         tg.makeTempdir()
1822         pkg := tg.path(".")
1823         tg.run("install", "-pkgdir", pkg, "sync")
1824         tg.mustExist(filepath.Join(pkg, "sync.a"))
1825         tg.mustNotExist(filepath.Join(pkg, "sync/atomic.a"))
1826         tg.run("install", "-i", "-pkgdir", pkg, "sync")
1827         tg.mustExist(filepath.Join(pkg, "sync.a"))
1828         tg.mustExist(filepath.Join(pkg, "sync/atomic.a"))
1829 }
1830
1831 // For issue 14337.
1832 func TestParallelTest(t *testing.T) {
1833         tooSlow(t)
1834         tg := testgo(t)
1835         tg.parallel()
1836         defer tg.cleanup()
1837         tg.makeTempdir()
1838         const testSrc = `package package_test
1839                 import (
1840                         "testing"
1841                 )
1842                 func TestTest(t *testing.T) {
1843                 }`
1844         tg.tempFile("src/p1/p1_test.go", strings.Replace(testSrc, "package_test", "p1_test", 1))
1845         tg.tempFile("src/p2/p2_test.go", strings.Replace(testSrc, "package_test", "p2_test", 1))
1846         tg.tempFile("src/p3/p3_test.go", strings.Replace(testSrc, "package_test", "p3_test", 1))
1847         tg.tempFile("src/p4/p4_test.go", strings.Replace(testSrc, "package_test", "p4_test", 1))
1848         tg.setenv("GOPATH", tg.path("."))
1849         tg.run("test", "-p=4", "p1", "p2", "p3", "p4")
1850 }
1851
1852 func TestBinaryOnlyPackages(t *testing.T) {
1853         tooSlow(t)
1854
1855         tg := testgo(t)
1856         defer tg.cleanup()
1857         tg.parallel()
1858         tg.makeTempdir()
1859         tg.setenv("GOPATH", tg.path("."))
1860
1861         tg.tempFile("src/p1/p1.go", `//go:binary-only-package
1862
1863                 package p1
1864         `)
1865         tg.wantStale("p1", "binary-only packages are no longer supported", "p1 is binary-only, and this message should always be printed")
1866         tg.runFail("install", "p1")
1867         tg.grepStderr("binary-only packages are no longer supported", "did not report attempt to compile binary-only package")
1868
1869         tg.tempFile("src/p1/p1.go", `
1870                 package p1
1871                 import "fmt"
1872                 func F(b bool) { fmt.Printf("hello from p1\n"); if b { F(false) } }
1873         `)
1874         tg.run("install", "p1")
1875         os.Remove(tg.path("src/p1/p1.go"))
1876         tg.mustNotExist(tg.path("src/p1/p1.go"))
1877
1878         tg.tempFile("src/p2/p2.go", `//go:binary-only-packages-are-not-great
1879
1880                 package p2
1881                 import "p1"
1882                 func F() { p1.F(true) }
1883         `)
1884         tg.runFail("install", "p2")
1885         tg.grepStderr("no Go files", "did not complain about missing sources")
1886
1887         tg.tempFile("src/p1/missing.go", `//go:binary-only-package
1888
1889                 package p1
1890                 import _ "fmt"
1891                 func G()
1892         `)
1893         tg.wantStale("p1", "binary-only package", "should NOT want to rebuild p1 (first)")
1894         tg.runFail("install", "p2")
1895         tg.grepStderr("p1: binary-only packages are no longer supported", "did not report error for binary-only p1")
1896
1897         tg.run("list", "-deps", "-f", "{{.ImportPath}}: {{.BinaryOnly}}", "p2")
1898         tg.grepStdout("p1: true", "p1 not listed as BinaryOnly")
1899         tg.grepStdout("p2: false", "p2 listed as BinaryOnly")
1900 }
1901
1902 // Issue 16050 and 21884.
1903 func TestLinkSysoFiles(t *testing.T) {
1904         if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
1905                 t.Skip("not linux/amd64")
1906         }
1907
1908         tg := testgo(t)
1909         defer tg.cleanup()
1910         tg.parallel()
1911         tg.tempDir("src/syso")
1912         tg.tempFile("src/syso/a.syso", ``)
1913         tg.tempFile("src/syso/b.go", `package syso`)
1914         tg.setenv("GOPATH", tg.path("."))
1915
1916         // We should see the .syso file regardless of the setting of
1917         // CGO_ENABLED.
1918
1919         tg.setenv("CGO_ENABLED", "1")
1920         tg.run("list", "-f", "{{.SysoFiles}}", "syso")
1921         tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=1")
1922
1923         tg.setenv("CGO_ENABLED", "0")
1924         tg.run("list", "-f", "{{.SysoFiles}}", "syso")
1925         tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=0")
1926
1927         tg.setenv("CGO_ENABLED", "1")
1928         tg.run("list", "-msan", "-f", "{{.SysoFiles}}", "syso")
1929         tg.grepStdoutNot("a.syso", "unexpected syso file with -msan")
1930 }
1931
1932 // Issue 16120.
1933 func TestGenerateUsesBuildContext(t *testing.T) {
1934         if runtime.GOOS == "windows" {
1935                 t.Skip("this test won't run under Windows")
1936         }
1937
1938         tg := testgo(t)
1939         defer tg.cleanup()
1940         tg.parallel()
1941         tg.tempDir("src/gen")
1942         tg.tempFile("src/gen/gen.go", "package gen\n//go:generate echo $GOOS $GOARCH\n")
1943         tg.setenv("GOPATH", tg.path("."))
1944
1945         tg.setenv("GOOS", "linux")
1946         tg.setenv("GOARCH", "amd64")
1947         tg.run("generate", "gen")
1948         tg.grepStdout("linux amd64", "unexpected GOOS/GOARCH combination")
1949
1950         tg.setenv("GOOS", "darwin")
1951         tg.setenv("GOARCH", "arm64")
1952         tg.run("generate", "gen")
1953         tg.grepStdout("darwin arm64", "unexpected GOOS/GOARCH combination")
1954 }
1955
1956 func TestGoEnv(t *testing.T) {
1957         tg := testgo(t)
1958         tg.parallel()
1959         defer tg.cleanup()
1960         tg.setenv("GOOS", "freebsd") // to avoid invalid pair errors
1961         tg.setenv("GOARCH", "arm")
1962         tg.run("env", "GOARCH")
1963         tg.grepStdout("^arm$", "GOARCH not honored")
1964
1965         tg.run("env", "GCCGO")
1966         tg.grepStdout(".", "GCCGO unexpectedly empty")
1967
1968         tg.run("env", "CGO_CFLAGS")
1969         tg.grepStdout(".", "default CGO_CFLAGS unexpectedly empty")
1970
1971         tg.setenv("CGO_CFLAGS", "-foobar")
1972         tg.run("env", "CGO_CFLAGS")
1973         tg.grepStdout("^-foobar$", "CGO_CFLAGS not honored")
1974
1975         tg.setenv("CC", "gcc -fmust -fgo -ffaster")
1976         tg.run("env", "CC")
1977         tg.grepStdout("gcc", "CC not found")
1978         tg.run("env", "GOGCCFLAGS")
1979         tg.grepStdout("-ffaster", "CC arguments not found")
1980
1981         tg.run("env", "GOVERSION")
1982         envVersion := strings.TrimSpace(tg.stdout.String())
1983
1984         tg.run("version")
1985         cmdVersion := strings.TrimSpace(tg.stdout.String())
1986
1987         // If 'go version' is "go version <version> <goos>/<goarch>", then
1988         // 'go env GOVERSION' is just "<version>".
1989         if cmdVersion == envVersion || !strings.Contains(cmdVersion, envVersion) {
1990                 t.Fatalf("'go env GOVERSION' %q should be a shorter substring of 'go version' %q", envVersion, cmdVersion)
1991         }
1992 }
1993
1994 const (
1995         noMatchesPattern = `(?m)^ok.*\[no tests to run\]`
1996         okPattern        = `(?m)^ok`
1997 )
1998
1999 // Issue 18044.
2000 func TestLdBindNow(t *testing.T) {
2001         tg := testgo(t)
2002         defer tg.cleanup()
2003         tg.parallel()
2004         tg.setenv("LD_BIND_NOW", "1")
2005         tg.run("help")
2006 }
2007
2008 // Issue 18225.
2009 // This is really a cmd/asm issue but this is a convenient place to test it.
2010 func TestConcurrentAsm(t *testing.T) {
2011         skipIfGccgo(t, "gccgo does not use cmd/asm")
2012         tg := testgo(t)
2013         defer tg.cleanup()
2014         tg.parallel()
2015         asm := `DATA ·constants<>+0x0(SB)/8,$0
2016 GLOBL ·constants<>(SB),8,$8
2017 `
2018         tg.tempFile("go/src/p/a.s", asm)
2019         tg.tempFile("go/src/p/b.s", asm)
2020         tg.tempFile("go/src/p/p.go", `package p`)
2021         tg.setenv("GOPATH", tg.path("go"))
2022         tg.run("build", "p")
2023 }
2024
2025 // Issue 18975.
2026 func TestFFLAGS(t *testing.T) {
2027         if !canCgo {
2028                 t.Skip("skipping because cgo not enabled")
2029         }
2030
2031         tg := testgo(t)
2032         defer tg.cleanup()
2033         tg.parallel()
2034
2035         tg.tempFile("p/src/p/main.go", `package main
2036                 // #cgo FFLAGS: -no-such-fortran-flag
2037                 import "C"
2038                 func main() {}
2039         `)
2040         tg.tempFile("p/src/p/a.f", `! comment`)
2041         tg.setenv("GOPATH", tg.path("p"))
2042
2043         // This should normally fail because we are passing an unknown flag,
2044         // but issue #19080 points to Fortran compilers that succeed anyhow.
2045         // To work either way we call doRun directly rather than run or runFail.
2046         tg.doRun([]string{"build", "-x", "p"})
2047
2048         tg.grepStderr("no-such-fortran-flag", `missing expected "-no-such-fortran-flag"`)
2049 }
2050
2051 // Issue 19198.
2052 // This is really a cmd/link issue but this is a convenient place to test it.
2053 func TestDuplicateGlobalAsmSymbols(t *testing.T) {
2054         skipIfGccgo(t, "gccgo does not use cmd/asm")
2055         tooSlow(t)
2056         if runtime.GOARCH != "386" && runtime.GOARCH != "amd64" {
2057                 t.Skipf("skipping test on %s", runtime.GOARCH)
2058         }
2059         if !canCgo {
2060                 t.Skip("skipping because cgo not enabled")
2061         }
2062
2063         tg := testgo(t)
2064         defer tg.cleanup()
2065         tg.parallel()
2066
2067         asm := `
2068 #include "textflag.h"
2069
2070 DATA sym<>+0x0(SB)/8,$0
2071 GLOBL sym<>(SB),(NOPTR+RODATA),$8
2072
2073 TEXT ·Data(SB),NOSPLIT,$0
2074         MOVB sym<>(SB), AX
2075         MOVB AX, ret+0(FP)
2076         RET
2077 `
2078         tg.tempFile("go/src/a/a.s", asm)
2079         tg.tempFile("go/src/a/a.go", `package a; func Data() uint8`)
2080         tg.tempFile("go/src/b/b.s", asm)
2081         tg.tempFile("go/src/b/b.go", `package b; func Data() uint8`)
2082         tg.tempFile("go/src/p/p.go", `
2083 package main
2084 import "a"
2085 import "b"
2086 import "C"
2087 func main() {
2088         _ = a.Data() + b.Data()
2089 }
2090 `)
2091         tg.setenv("GOPATH", tg.path("go"))
2092         exe := tg.path("p.exe")
2093         tg.creatingTemp(exe)
2094         tg.run("build", "-o", exe, "p")
2095 }
2096
2097 func copyFile(src, dst string, perm fs.FileMode) error {
2098         sf, err := os.Open(src)
2099         if err != nil {
2100                 return err
2101         }
2102         defer sf.Close()
2103
2104         df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
2105         if err != nil {
2106                 return err
2107         }
2108
2109         _, err = io.Copy(df, sf)
2110         err2 := df.Close()
2111         if err != nil {
2112                 return err
2113         }
2114         return err2
2115 }
2116
2117 func TestNeedVersion(t *testing.T) {
2118         skipIfGccgo(t, "gccgo does not use cmd/compile")
2119         tg := testgo(t)
2120         defer tg.cleanup()
2121         tg.parallel()
2122         tg.tempFile("goversion.go", `package main; func main() {}`)
2123         path := tg.path("goversion.go")
2124         tg.setenv("TESTGO_VERSION", "go1.testgo")
2125         tg.runFail("run", path)
2126         tg.grepStderr("compile", "does not match go tool version")
2127 }
2128
2129 func TestBuildmodePIE(t *testing.T) {
2130         if testing.Short() && testenv.Builder() == "" {
2131                 t.Skipf("skipping in -short mode on non-builder")
2132         }
2133
2134         platform := fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)
2135         switch platform {
2136         case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/riscv64", "linux/s390x",
2137                 "android/amd64", "android/arm", "android/arm64", "android/386",
2138                 "freebsd/amd64",
2139                 "windows/386", "windows/amd64", "windows/arm":
2140         case "darwin/amd64":
2141         default:
2142                 t.Skipf("skipping test because buildmode=pie is not supported on %s", platform)
2143         }
2144         t.Run("non-cgo", func(t *testing.T) {
2145                 testBuildmodePIE(t, false, true)
2146         })
2147         if canCgo {
2148                 switch runtime.GOOS {
2149                 case "darwin", "freebsd", "linux", "windows":
2150                         t.Run("cgo", func(t *testing.T) {
2151                                 testBuildmodePIE(t, true, true)
2152                         })
2153                 }
2154         }
2155 }
2156
2157 func TestWindowsDefaultBuildmodIsPIE(t *testing.T) {
2158         if testing.Short() && testenv.Builder() == "" {
2159                 t.Skipf("skipping in -short mode on non-builder")
2160         }
2161
2162         if runtime.GOOS != "windows" {
2163                 t.Skip("skipping windows only test")
2164         }
2165
2166         t.Run("non-cgo", func(t *testing.T) {
2167                 testBuildmodePIE(t, false, false)
2168         })
2169         if canCgo {
2170                 t.Run("cgo", func(t *testing.T) {
2171                         testBuildmodePIE(t, true, false)
2172                 })
2173         }
2174 }
2175
2176 func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) {
2177         tg := testgo(t)
2178         defer tg.cleanup()
2179         tg.parallel()
2180
2181         var s string
2182         if useCgo {
2183                 s = `import "C";`
2184         }
2185         tg.tempFile("main.go", fmt.Sprintf(`package main;%s func main() { print("hello") }`, s))
2186         src := tg.path("main.go")
2187         obj := tg.path("main.exe")
2188         args := []string{"build"}
2189         if setBuildmodeToPIE {
2190                 args = append(args, "-buildmode=pie")
2191         }
2192         args = append(args, "-o", obj, src)
2193         tg.run(args...)
2194
2195         switch runtime.GOOS {
2196         case "linux", "android", "freebsd":
2197                 f, err := elf.Open(obj)
2198                 if err != nil {
2199                         t.Fatal(err)
2200                 }
2201                 defer f.Close()
2202                 if f.Type != elf.ET_DYN {
2203                         t.Errorf("PIE type must be ET_DYN, but %s", f.Type)
2204                 }
2205         case "darwin":
2206                 f, err := macho.Open(obj)
2207                 if err != nil {
2208                         t.Fatal(err)
2209                 }
2210                 defer f.Close()
2211                 if f.Flags&macho.FlagDyldLink == 0 {
2212                         t.Error("PIE must have DyldLink flag, but not")
2213                 }
2214                 if f.Flags&macho.FlagPIE == 0 {
2215                         t.Error("PIE must have PIE flag, but not")
2216                 }
2217         case "windows":
2218                 f, err := pe.Open(obj)
2219                 if err != nil {
2220                         t.Fatal(err)
2221                 }
2222                 defer f.Close()
2223                 if f.Section(".reloc") == nil {
2224                         t.Error(".reloc section is not present")
2225                 }
2226                 if (f.FileHeader.Characteristics & pe.IMAGE_FILE_RELOCS_STRIPPED) != 0 {
2227                         t.Error("IMAGE_FILE_RELOCS_STRIPPED flag is set")
2228                 }
2229                 var dc uint16
2230                 switch oh := f.OptionalHeader.(type) {
2231                 case *pe.OptionalHeader32:
2232                         dc = oh.DllCharacteristics
2233                 case *pe.OptionalHeader64:
2234                         dc = oh.DllCharacteristics
2235                         if (dc & pe.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) == 0 {
2236                                 t.Error("IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA flag is not set")
2237                         }
2238                 default:
2239                         t.Fatalf("unexpected optional header type of %T", f.OptionalHeader)
2240                 }
2241                 if (dc & pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 {
2242                         t.Error("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag is not set")
2243                 }
2244                 if useCgo {
2245                         // Test that only one symbol is exported (#40795).
2246                         // PIE binaries don´t require .edata section but unfortunately
2247                         // binutils doesn´t generate a .reloc section unless there is
2248                         // at least one symbol exported.
2249                         // See https://sourceware.org/bugzilla/show_bug.cgi?id=19011
2250                         section := f.Section(".edata")
2251                         if section == nil {
2252                                 t.Skip(".edata section is not present")
2253                         }
2254                         // TODO: deduplicate this struct from cmd/link/internal/ld/pe.go
2255                         type IMAGE_EXPORT_DIRECTORY struct {
2256                                 _                 [2]uint32
2257                                 _                 [2]uint16
2258                                 _                 [2]uint32
2259                                 NumberOfFunctions uint32
2260                                 NumberOfNames     uint32
2261                                 _                 [3]uint32
2262                         }
2263                         var e IMAGE_EXPORT_DIRECTORY
2264                         if err := binary.Read(section.Open(), binary.LittleEndian, &e); err != nil {
2265                                 t.Fatalf("binary.Read failed: %v", err)
2266                         }
2267
2268                         // Only _cgo_dummy_export should be exported
2269                         if e.NumberOfFunctions != 1 {
2270                                 t.Fatalf("got %d exported functions; want 1", e.NumberOfFunctions)
2271                         }
2272                         if e.NumberOfNames != 1 {
2273                                 t.Fatalf("got %d exported names; want 1", e.NumberOfNames)
2274                         }
2275                 }
2276         default:
2277                 panic("unreachable")
2278         }
2279
2280         out, err := exec.Command(obj).CombinedOutput()
2281         if err != nil {
2282                 t.Fatal(err)
2283         }
2284
2285         if string(out) != "hello" {
2286                 t.Errorf("got %q; want %q", out, "hello")
2287         }
2288 }
2289
2290 func TestUpxCompression(t *testing.T) {
2291         if runtime.GOOS != "linux" ||
2292                 (runtime.GOARCH != "amd64" && runtime.GOARCH != "386") {
2293                 t.Skipf("skipping upx test on %s/%s", runtime.GOOS, runtime.GOARCH)
2294         }
2295
2296         testenv.MustHaveExecPath(t, "upx")
2297         out, err := exec.Command("upx", "--version").CombinedOutput()
2298         if err != nil {
2299                 t.Fatalf("upx --version failed: %v", err)
2300         }
2301
2302         // upx --version prints `upx <version>` in the first line of output:
2303         //   upx 3.94
2304         //   [...]
2305         re := regexp.MustCompile(`([[:digit:]]+)\.([[:digit:]]+)`)
2306         upxVersion := re.FindStringSubmatch(string(out))
2307         if len(upxVersion) != 3 {
2308                 t.Fatalf("bad upx version string: %s", upxVersion)
2309         }
2310
2311         major, err1 := strconv.Atoi(upxVersion[1])
2312         minor, err2 := strconv.Atoi(upxVersion[2])
2313         if err1 != nil || err2 != nil {
2314                 t.Fatalf("bad upx version string: %s", upxVersion[0])
2315         }
2316
2317         // Anything below 3.94 is known not to work with go binaries
2318         if (major < 3) || (major == 3 && minor < 94) {
2319                 t.Skipf("skipping because upx version %v.%v is too old", major, minor)
2320         }
2321
2322         tg := testgo(t)
2323         defer tg.cleanup()
2324         tg.parallel()
2325
2326         tg.tempFile("main.go", `package main; import "fmt"; func main() { fmt.Print("hello upx") }`)
2327         src := tg.path("main.go")
2328         obj := tg.path("main")
2329         tg.run("build", "-o", obj, src)
2330
2331         out, err = exec.Command("upx", obj).CombinedOutput()
2332         if err != nil {
2333                 t.Logf("executing upx\n%s\n", out)
2334                 t.Fatalf("upx failed with %v", err)
2335         }
2336
2337         out, err = exec.Command(obj).CombinedOutput()
2338         if err != nil {
2339                 t.Logf("%s", out)
2340                 t.Fatalf("running compressed go binary failed with error %s", err)
2341         }
2342         if string(out) != "hello upx" {
2343                 t.Fatalf("bad output from compressed go binary:\ngot %q; want %q", out, "hello upx")
2344         }
2345 }
2346
2347 func TestCacheListStale(t *testing.T) {
2348         tooSlow(t)
2349         if godebug.Get("gocacheverify") == "1" {
2350                 t.Skip("GODEBUG gocacheverify")
2351         }
2352         tg := testgo(t)
2353         defer tg.cleanup()
2354         tg.parallel()
2355         tg.makeTempdir()
2356         tg.setenv("GOCACHE", tg.path("cache"))
2357         tg.tempFile("gopath/src/p/p.go", "package p; import _ \"q\"; func F(){}\n")
2358         tg.tempFile("gopath/src/q/q.go", "package q; func F(){}\n")
2359         tg.tempFile("gopath/src/m/m.go", "package main; import _ \"q\"; func main(){}\n")
2360
2361         tg.setenv("GOPATH", tg.path("gopath"))
2362         tg.run("install", "p", "m")
2363         tg.run("list", "-f={{.ImportPath}} {{.Stale}}", "m", "q", "p")
2364         tg.grepStdout("^m false", "m should not be stale")
2365         tg.grepStdout("^q true", "q should be stale")
2366         tg.grepStdout("^p false", "p should not be stale")
2367 }
2368
2369 func TestCacheCoverage(t *testing.T) {
2370         tooSlow(t)
2371
2372         if godebug.Get("gocacheverify") == "1" {
2373                 t.Skip("GODEBUG gocacheverify")
2374         }
2375
2376         tg := testgo(t)
2377         defer tg.cleanup()
2378         tg.parallel()
2379         tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
2380         tg.makeTempdir()
2381
2382         tg.setenv("GOCACHE", tg.path("c1"))
2383         tg.run("test", "-cover", "-short", "strings")
2384         tg.run("test", "-cover", "-short", "math", "strings")
2385 }
2386
2387 func TestIssue22588(t *testing.T) {
2388         // Don't get confused by stderr coming from tools.
2389         tg := testgo(t)
2390         defer tg.cleanup()
2391         tg.parallel()
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         // don't let install -i overwrite runtime
2637         tg.wantNotStale("runtime", "", "must be non-stale before install -i")
2638
2639         tg.run("install", "-i", "main1")
2640         tg.mustExist(p1)
2641         tg.must(os.Remove(p1))
2642
2643         tg.run("install", "-i", "p2")
2644         tg.mustExist(p1)
2645 }
2646
2647 // Issue 22986.
2648 func TestImportPath(t *testing.T) {
2649         tooSlow(t)
2650         tg := testgo(t)
2651         defer tg.cleanup()
2652         tg.parallel()
2653
2654         tg.tempFile("src/a/a.go", `
2655 package main
2656
2657 import (
2658         "log"
2659         p "a/p-1.0"
2660 )
2661
2662 func main() {
2663         if !p.V {
2664                 log.Fatal("false")
2665         }
2666 }`)
2667
2668         tg.tempFile("src/a/a_test.go", `
2669 package main_test
2670
2671 import (
2672         p "a/p-1.0"
2673         "testing"
2674 )
2675
2676 func TestV(t *testing.T) {
2677         if !p.V {
2678                 t.Fatal("false")
2679         }
2680 }`)
2681
2682         tg.tempFile("src/a/p-1.0/p.go", `
2683 package p
2684
2685 var V = true
2686
2687 func init() {}
2688 `)
2689
2690         tg.setenv("GOPATH", tg.path("."))
2691         tg.run("build", "-o", tg.path("a.exe"), "a")
2692         tg.run("test", "a")
2693 }
2694
2695 func TestBadCommandLines(t *testing.T) {
2696         tg := testgo(t)
2697         defer tg.cleanup()
2698         tg.parallel()
2699
2700         tg.tempFile("src/x/x.go", "package x\n")
2701         tg.setenv("GOPATH", tg.path("."))
2702
2703         tg.run("build", "x")
2704
2705         tg.tempFile("src/x/@y.go", "package x\n")
2706         tg.runFail("build", "x")
2707         tg.grepStderr("invalid input file name \"@y.go\"", "did not reject @y.go")
2708         tg.must(os.Remove(tg.path("src/x/@y.go")))
2709
2710         tg.tempFile("src/x/-y.go", "package x\n")
2711         tg.runFail("build", "x")
2712         tg.grepStderr("invalid input file name \"-y.go\"", "did not reject -y.go")
2713         tg.must(os.Remove(tg.path("src/x/-y.go")))
2714
2715         if runtime.Compiler == "gccgo" {
2716                 tg.runFail("build", "-gccgoflags=all=@x", "x")
2717         } else {
2718                 tg.runFail("build", "-gcflags=all=@x", "x")
2719         }
2720         tg.grepStderr("invalid command-line argument @x in command", "did not reject @x during exec")
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 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")
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\"|can only use path@version syntax with 'go get' and 'go install' in module-aware mode", "did not reject @x/y import path")
2731
2732         tg.tempFile("src/-x/x.go", "package x\n")
2733         tg.setenv("GOPATH", tg.path("."))
2734         tg.runFail("build", "--", "-x")
2735         tg.grepStderr("invalid import path \"-x\"", "did not reject -x import path")
2736
2737         tg.tempFile("src/-x/y/y.go", "package y\n")
2738         tg.setenv("GOPATH", tg.path("."))
2739         tg.runFail("build", "--", "-x/y")
2740         tg.grepStderr("invalid import path \"-x/y\"", "did not reject -x/y import path")
2741 }
2742
2743 func TestTwoPkgConfigs(t *testing.T) {
2744         if !canCgo {
2745                 t.Skip("no cgo")
2746         }
2747         if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
2748                 t.Skipf("no shell scripts on %s", runtime.GOOS)
2749         }
2750         tooSlow(t)
2751         tg := testgo(t)
2752         defer tg.cleanup()
2753         tg.parallel()
2754         tg.tempFile("src/x/a.go", `package x
2755                 // #cgo pkg-config: --static a
2756                 import "C"
2757         `)
2758         tg.tempFile("src/x/b.go", `package x
2759                 // #cgo pkg-config: --static a
2760                 import "C"
2761         `)
2762         tg.tempFile("pkg-config.sh", `#!/bin/sh
2763 echo $* >>`+tg.path("pkg-config.out"))
2764         tg.must(os.Chmod(tg.path("pkg-config.sh"), 0755))
2765         tg.setenv("GOPATH", tg.path("."))
2766         tg.setenv("PKG_CONFIG", tg.path("pkg-config.sh"))
2767         tg.run("build", "x")
2768         out, err := os.ReadFile(tg.path("pkg-config.out"))
2769         tg.must(err)
2770         out = bytes.TrimSpace(out)
2771         want := "--cflags --static --static -- a a\n--libs --static --static -- a a"
2772         if !bytes.Equal(out, []byte(want)) {
2773                 t.Errorf("got %q want %q", out, want)
2774         }
2775 }
2776
2777 func TestCgoCache(t *testing.T) {
2778         if !canCgo {
2779                 t.Skip("no cgo")
2780         }
2781         tooSlow(t)
2782
2783         tg := testgo(t)
2784         defer tg.cleanup()
2785         tg.parallel()
2786         tg.tempFile("src/x/a.go", `package main
2787                 // #ifndef VAL
2788                 // #define VAL 0
2789                 // #endif
2790                 // int val = VAL;
2791                 import "C"
2792                 import "fmt"
2793                 func main() { fmt.Println(C.val) }
2794         `)
2795         tg.setenv("GOPATH", tg.path("."))
2796         exe := tg.path("x.exe")
2797         tg.run("build", "-o", exe, "x")
2798         tg.setenv("CGO_LDFLAGS", "-lnosuchlibraryexists")
2799         tg.runFail("build", "-o", exe, "x")
2800         tg.grepStderr(`nosuchlibraryexists`, "did not run linker with changed CGO_LDFLAGS")
2801 }
2802
2803 // Issue 23982
2804 func TestFilepathUnderCwdFormat(t *testing.T) {
2805         tg := testgo(t)
2806         defer tg.cleanup()
2807         tg.parallel()
2808         tg.run("test", "-x", "-cover", "log")
2809         tg.grepStderrNot(`\.log\.cover\.go`, "-x output should contain correctly formatted filepath under cwd")
2810 }
2811
2812 // Issue 24396.
2813 func TestDontReportRemoveOfEmptyDir(t *testing.T) {
2814         tg := testgo(t)
2815         defer tg.cleanup()
2816         tg.parallel()
2817         tg.tempFile("src/a/a.go", `package a`)
2818         tg.setenv("GOPATH", tg.path("."))
2819         tg.run("install", "-x", "a")
2820         tg.run("install", "-x", "a")
2821         // The second install should have printed only a WORK= line,
2822         // nothing else.
2823         if bytes.Count(tg.stdout.Bytes(), []byte{'\n'})+bytes.Count(tg.stderr.Bytes(), []byte{'\n'}) > 1 {
2824                 t.Error("unnecessary output when installing installed package")
2825         }
2826 }
2827
2828 // Issue 24704.
2829 func TestLinkerTmpDirIsDeleted(t *testing.T) {
2830         skipIfGccgo(t, "gccgo does not use cmd/link")
2831         if !canCgo {
2832                 t.Skip("skipping because cgo not enabled")
2833         }
2834         tooSlow(t)
2835
2836         tg := testgo(t)
2837         defer tg.cleanup()
2838         tg.parallel()
2839         tg.tempFile("a.go", `package main; import "C"; func main() {}`)
2840         tg.run("build", "-ldflags", "-v", "-o", os.DevNull, tg.path("a.go"))
2841         // Find line that has "host link:" in linker output.
2842         stderr := tg.getStderr()
2843         var hostLinkLine string
2844         for _, line := range strings.Split(stderr, "\n") {
2845                 if !strings.Contains(line, "host link:") {
2846                         continue
2847                 }
2848                 hostLinkLine = line
2849                 break
2850         }
2851         if hostLinkLine == "" {
2852                 t.Fatal(`fail to find with "host link:" string in linker output`)
2853         }
2854         // Find parameter, like "/tmp/go-link-408556474/go.o" inside of
2855         // "host link:" line, and extract temp directory /tmp/go-link-408556474
2856         // out of it.
2857         tmpdir := hostLinkLine
2858         i := strings.Index(tmpdir, `go.o"`)
2859         if i == -1 {
2860                 t.Fatalf(`fail to find "go.o" in "host link:" line %q`, hostLinkLine)
2861         }
2862         tmpdir = tmpdir[:i-1]
2863         i = strings.LastIndex(tmpdir, `"`)
2864         if i == -1 {
2865                 t.Fatalf(`fail to find " in "host link:" line %q`, hostLinkLine)
2866         }
2867         tmpdir = tmpdir[i+1:]
2868         // Verify that temp directory has been removed.
2869         _, err := os.Stat(tmpdir)
2870         if err == nil {
2871                 t.Fatalf("temp directory %q has not been removed", tmpdir)
2872         }
2873         if !os.IsNotExist(err) {
2874                 t.Fatalf("Stat(%q) returns unexpected error: %v", tmpdir, err)
2875         }
2876 }
2877
2878 // Issue 25093.
2879 func TestCoverpkgTestOnly(t *testing.T) {
2880         skipIfGccgo(t, "gccgo has no cover tool")
2881         tooSlow(t)
2882         tg := testgo(t)
2883         defer tg.cleanup()
2884         tg.parallel()
2885         tg.tempFile("src/a/a.go", `package a
2886                 func F(i int) int {
2887                         return i*i
2888                 }`)
2889         tg.tempFile("src/atest/a_test.go", `
2890                 package a_test
2891                 import ( "a"; "testing" )
2892                 func TestF(t *testing.T) { a.F(2) }
2893         `)
2894         tg.setenv("GOPATH", tg.path("."))
2895         tg.run("test", "-coverpkg=a", "atest")
2896         tg.grepStderrNot("no packages being tested depend on matches", "bad match message")
2897         tg.grepStdout("coverage: 100", "no coverage")
2898 }
2899
2900 // Regression test for golang.org/issue/34499: version command should not crash
2901 // when executed in a deleted directory on Linux.
2902 func TestExecInDeletedDir(t *testing.T) {
2903         switch runtime.GOOS {
2904         case "windows", "plan9",
2905                 "aix",                // Fails with "device busy".
2906                 "solaris", "illumos": // Fails with "invalid argument".
2907                 t.Skipf("%v does not support removing the current working directory", runtime.GOOS)
2908         }
2909         tg := testgo(t)
2910         defer tg.cleanup()
2911
2912         wd, err := os.Getwd()
2913         tg.check(err)
2914         tg.makeTempdir()
2915         tg.check(os.Chdir(tg.tempdir))
2916         defer func() { tg.check(os.Chdir(wd)) }()
2917
2918         tg.check(os.Remove(tg.tempdir))
2919
2920         // `go version` should not fail
2921         tg.run("version")
2922 }
2923
2924 // A missing C compiler should not force the net package to be stale.
2925 // Issue 47215.
2926 func TestMissingCC(t *testing.T) {
2927         if !canCgo {
2928                 t.Skip("test is only meaningful on systems with cgo")
2929         }
2930         cc := os.Getenv("CC")
2931         if cc == "" {
2932                 cc = "gcc"
2933         }
2934         if filepath.IsAbs(cc) {
2935                 t.Skipf(`"CC" (%s) is an absolute path`, cc)
2936         }
2937         _, err := exec.LookPath(cc)
2938         if err != nil {
2939                 t.Skipf(`"CC" (%s) not on PATH`, cc)
2940         }
2941
2942         tg := testgo(t)
2943         defer tg.cleanup()
2944         netStale, _ := tg.isStale("net")
2945         if netStale {
2946                 t.Skip(`skipping test because "net" package is currently stale`)
2947         }
2948
2949         tg.setenv("PATH", "") // No C compiler on PATH.
2950         netStale, _ = tg.isStale("net")
2951         if netStale {
2952                 t.Error(`clearing "PATH" causes "net" to be stale`)
2953         }
2954 }