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