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