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
5package main_test
6
7import (
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
38func 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
46var (
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
55var exeSuffix string = func() string {
56	if runtime.GOOS == "windows" {
57		return ".exe"
58	}
59	return ""
60}()
61
62func 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.
76var testGOROOT string
77
78var testGOCACHE string
79
80var testGo string
81var testTmpDir string
82var testBin string
83
84// The TestMain function creates a go command for testing purposes and
85// deletes it after the tests have been run.
86func 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
255func 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).
267var mtimeTick time.Duration = 1 * time.Second
268
269// Manage a single run of the testgo binary.
270type 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.
282func 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.
289func 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.
298func (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.
306func (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.
314func (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.
332func (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.
344func (tg *testgoData) sleep() {
345	time.Sleep(mtimeTick)
346}
347
348// setenv sets an environment variable to use when running the test go
349// command.
350func (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.
360func (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
373func (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.
379func (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.
423func (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.
433func (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.
443func (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.
468func (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.
477func (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.
488func (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.
506func (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.
517func (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.
524func (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.
531func (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.
542func (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.
553func (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.
560func (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.
568func (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.
577func (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.
594func (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.
603func (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.
614func (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.
624func (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.
639func (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.
649func (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.
661func (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.
672func (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.
681func (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.
693func (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
708func (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.
726func (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.
742func (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.
756var testWork = flag.Bool("testwork", false, "")
757
758// cleanup cleans up a test that runs testgo.
759func (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
773func 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.
789func (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
799func 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.
910func 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
926func 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.
942func 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
967func 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.
993func 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
1015func 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.
1029func 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
1040func 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
1053func 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
1062func 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
1078func 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
1109func 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/buildid", "cmd/doc")
1132	tg.grepStdout(`^cmd/buildid$`, "missing cmd/buildid")
1133	tg.grepStdout(`^cmd/doc$`, "missing cmd/doc")
1134	tg.grepStdout(`^cmd/doc\.test$`, "missing cmd/doc test")
1135	tg.grepStdoutNot(`^cmd/buildid\.test$`, "unexpected cmd/buildid 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
1146func 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
1183func 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.
1218func 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
1228func 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
1238func 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,
1251func 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.
1264func 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
1276func 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
1287func 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
1298func 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
1317func 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
1345func 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
1357func 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
1372func 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
1396func 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
1407func 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
1418func 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.
1435func 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.
1463func 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
1487func 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
1504func 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
1522func 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", `
1543Name: foo
1544Description: The foo library
1545Version: 1.0.0
1546Cflags: -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
1552int value() {
1553	return DEFINED_FROM_PKG_CONFIG;
1554}
1555*/
1556import "C"
1557import "os"
1558
1559func 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
1570func 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.
1607func 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
1758func 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.
1776func 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
1796func 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.
1847func TestAlwaysLinkSysoFiles(t *testing.T) {
1848	tg := testgo(t)
1849	defer tg.cleanup()
1850	tg.parallel()
1851	tg.tempDir("src/syso")
1852	tg.tempFile("src/syso/a.syso", ``)
1853	tg.tempFile("src/syso/b.go", `package syso`)
1854	tg.setenv("GOPATH", tg.path("."))
1855
1856	// We should see the .syso file regardless of the setting of
1857	// CGO_ENABLED.
1858
1859	tg.setenv("CGO_ENABLED", "1")
1860	tg.run("list", "-f", "{{.SysoFiles}}", "syso")
1861	tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=1")
1862
1863	tg.setenv("CGO_ENABLED", "0")
1864	tg.run("list", "-f", "{{.SysoFiles}}", "syso")
1865	tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=0")
1866}
1867
1868// Issue 16120.
1869func TestGenerateUsesBuildContext(t *testing.T) {
1870	if runtime.GOOS == "windows" {
1871		t.Skip("this test won't run under Windows")
1872	}
1873
1874	tg := testgo(t)
1875	defer tg.cleanup()
1876	tg.parallel()
1877	tg.tempDir("src/gen")
1878	tg.tempFile("src/gen/gen.go", "package gen\n//go:generate echo $GOOS $GOARCH\n")
1879	tg.setenv("GOPATH", tg.path("."))
1880
1881	tg.setenv("GOOS", "linux")
1882	tg.setenv("GOARCH", "amd64")
1883	tg.run("generate", "gen")
1884	tg.grepStdout("linux amd64", "unexpected GOOS/GOARCH combination")
1885
1886	tg.setenv("GOOS", "darwin")
1887	tg.setenv("GOARCH", "arm64")
1888	tg.run("generate", "gen")
1889	tg.grepStdout("darwin arm64", "unexpected GOOS/GOARCH combination")
1890}
1891
1892func TestGoEnv(t *testing.T) {
1893	tg := testgo(t)
1894	tg.parallel()
1895	defer tg.cleanup()
1896	tg.setenv("GOOS", "freebsd") // to avoid invalid pair errors
1897	tg.setenv("GOARCH", "arm")
1898	tg.run("env", "GOARCH")
1899	tg.grepStdout("^arm$", "GOARCH not honored")
1900
1901	tg.run("env", "GCCGO")
1902	tg.grepStdout(".", "GCCGO unexpectedly empty")
1903
1904	tg.run("env", "CGO_CFLAGS")
1905	tg.grepStdout(".", "default CGO_CFLAGS unexpectedly empty")
1906
1907	tg.setenv("CGO_CFLAGS", "-foobar")
1908	tg.run("env", "CGO_CFLAGS")
1909	tg.grepStdout("^-foobar$", "CGO_CFLAGS not honored")
1910
1911	tg.setenv("CC", "gcc -fmust -fgo -ffaster")
1912	tg.run("env", "CC")
1913	tg.grepStdout("gcc", "CC not found")
1914	tg.run("env", "GOGCCFLAGS")
1915	tg.grepStdout("-ffaster", "CC arguments not found")
1916
1917	tg.run("env", "GOVERSION")
1918	envVersion := strings.TrimSpace(tg.stdout.String())
1919
1920	tg.run("version")
1921	cmdVersion := strings.TrimSpace(tg.stdout.String())
1922
1923	// If 'go version' is "go version <version> <goos>/<goarch>", then
1924	// 'go env GOVERSION' is just "<version>".
1925	if cmdVersion == envVersion || !strings.Contains(cmdVersion, envVersion) {
1926		t.Fatalf("'go env GOVERSION' %q should be a shorter substring of 'go version' %q", envVersion, cmdVersion)
1927	}
1928}
1929
1930const (
1931	noMatchesPattern = `(?m)^ok.*\[no tests to run\]`
1932	okPattern        = `(?m)^ok`
1933)
1934
1935// Issue 18044.
1936func TestLdBindNow(t *testing.T) {
1937	tg := testgo(t)
1938	defer tg.cleanup()
1939	tg.parallel()
1940	tg.setenv("LD_BIND_NOW", "1")
1941	tg.run("help")
1942}
1943
1944// Issue 18225.
1945// This is really a cmd/asm issue but this is a convenient place to test it.
1946func TestConcurrentAsm(t *testing.T) {
1947	skipIfGccgo(t, "gccgo does not use cmd/asm")
1948	tg := testgo(t)
1949	defer tg.cleanup()
1950	tg.parallel()
1951	asm := `DATA ·constants<>+0x0(SB)/8,$0
1952GLOBL ·constants<>(SB),8,$8
1953`
1954	tg.tempFile("go/src/p/a.s", asm)
1955	tg.tempFile("go/src/p/b.s", asm)
1956	tg.tempFile("go/src/p/p.go", `package p`)
1957	tg.setenv("GOPATH", tg.path("go"))
1958	tg.run("build", "p")
1959}
1960
1961// Issue 18975.
1962func TestFFLAGS(t *testing.T) {
1963	if !canCgo {
1964		t.Skip("skipping because cgo not enabled")
1965	}
1966
1967	tg := testgo(t)
1968	defer tg.cleanup()
1969	tg.parallel()
1970
1971	tg.tempFile("p/src/p/main.go", `package main
1972		// #cgo FFLAGS: -no-such-fortran-flag
1973		import "C"
1974		func main() {}
1975	`)
1976	tg.tempFile("p/src/p/a.f", `! comment`)
1977	tg.setenv("GOPATH", tg.path("p"))
1978
1979	// This should normally fail because we are passing an unknown flag,
1980	// but issue #19080 points to Fortran compilers that succeed anyhow.
1981	// To work either way we call doRun directly rather than run or runFail.
1982	tg.doRun([]string{"build", "-x", "p"})
1983
1984	tg.grepStderr("no-such-fortran-flag", `missing expected "-no-such-fortran-flag"`)
1985}
1986
1987// Issue 19198.
1988// This is really a cmd/link issue but this is a convenient place to test it.
1989func TestDuplicateGlobalAsmSymbols(t *testing.T) {
1990	skipIfGccgo(t, "gccgo does not use cmd/asm")
1991	tooSlow(t)
1992	if runtime.GOARCH != "386" && runtime.GOARCH != "amd64" {
1993		t.Skipf("skipping test on %s", runtime.GOARCH)
1994	}
1995	if !canCgo {
1996		t.Skip("skipping because cgo not enabled")
1997	}
1998
1999	tg := testgo(t)
2000	defer tg.cleanup()
2001	tg.parallel()
2002
2003	asm := `
2004#include "textflag.h"
2005
2006DATA sym<>+0x0(SB)/8,$0
2007GLOBL sym<>(SB),(NOPTR+RODATA),$8
2008
2009TEXT ·Data(SB),NOSPLIT,$0
2010	MOVB sym<>(SB), AX
2011	MOVB AX, ret+0(FP)
2012	RET
2013`
2014	tg.tempFile("go/src/a/a.s", asm)
2015	tg.tempFile("go/src/a/a.go", `package a; func Data() uint8`)
2016	tg.tempFile("go/src/b/b.s", asm)
2017	tg.tempFile("go/src/b/b.go", `package b; func Data() uint8`)
2018	tg.tempFile("go/src/p/p.go", `
2019package main
2020import "a"
2021import "b"
2022import "C"
2023func main() {
2024	_ = a.Data() + b.Data()
2025}
2026`)
2027	tg.setenv("GOPATH", tg.path("go"))
2028	exe := tg.path("p.exe")
2029	tg.creatingTemp(exe)
2030	tg.run("build", "-o", exe, "p")
2031}
2032
2033func copyFile(src, dst string, perm fs.FileMode) error {
2034	sf, err := os.Open(src)
2035	if err != nil {
2036		return err
2037	}
2038	defer sf.Close()
2039
2040	df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
2041	if err != nil {
2042		return err
2043	}
2044
2045	_, err = io.Copy(df, sf)
2046	err2 := df.Close()
2047	if err != nil {
2048		return err
2049	}
2050	return err2
2051}
2052
2053func TestNeedVersion(t *testing.T) {
2054	skipIfGccgo(t, "gccgo does not use cmd/compile")
2055	tg := testgo(t)
2056	defer tg.cleanup()
2057	tg.parallel()
2058	tg.tempFile("goversion.go", `package main; func main() {}`)
2059	path := tg.path("goversion.go")
2060	tg.setenv("TESTGO_VERSION", "go1.testgo")
2061	tg.runFail("run", path)
2062	tg.grepStderr("compile", "does not match go tool version")
2063}
2064
2065func TestBuildmodePIE(t *testing.T) {
2066	if testing.Short() && testenv.Builder() == "" {
2067		t.Skipf("skipping in -short mode on non-builder")
2068	}
2069
2070	platform := fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)
2071	switch platform {
2072	case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/riscv64", "linux/s390x",
2073		"android/amd64", "android/arm", "android/arm64", "android/386",
2074		"freebsd/amd64",
2075		"windows/386", "windows/amd64", "windows/arm":
2076	case "darwin/amd64":
2077	default:
2078		t.Skipf("skipping test because buildmode=pie is not supported on %s", platform)
2079	}
2080	t.Run("non-cgo", func(t *testing.T) {
2081		testBuildmodePIE(t, false, true)
2082	})
2083	if canCgo {
2084		switch runtime.GOOS {
2085		case "darwin", "freebsd", "linux", "windows":
2086			t.Run("cgo", func(t *testing.T) {
2087				testBuildmodePIE(t, true, true)
2088			})
2089		}
2090	}
2091}
2092
2093func TestWindowsDefaultBuildmodIsPIE(t *testing.T) {
2094	if testing.Short() && testenv.Builder() == "" {
2095		t.Skipf("skipping in -short mode on non-builder")
2096	}
2097
2098	if runtime.GOOS != "windows" {
2099		t.Skip("skipping windows only test")
2100	}
2101
2102	t.Run("non-cgo", func(t *testing.T) {
2103		testBuildmodePIE(t, false, false)
2104	})
2105	if canCgo {
2106		t.Run("cgo", func(t *testing.T) {
2107			testBuildmodePIE(t, true, false)
2108		})
2109	}
2110}
2111
2112func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) {
2113	tg := testgo(t)
2114	defer tg.cleanup()
2115	tg.parallel()
2116
2117	var s string
2118	if useCgo {
2119		s = `import "C";`
2120	}
2121	tg.tempFile("main.go", fmt.Sprintf(`package main;%s func main() { print("hello") }`, s))
2122	src := tg.path("main.go")
2123	obj := tg.path("main.exe")
2124	args := []string{"build"}
2125	if setBuildmodeToPIE {
2126		args = append(args, "-buildmode=pie")
2127	}
2128	args = append(args, "-o", obj, src)
2129	tg.run(args...)
2130
2131	switch runtime.GOOS {
2132	case "linux", "android", "freebsd":
2133		f, err := elf.Open(obj)
2134		if err != nil {
2135			t.Fatal(err)
2136		}
2137		defer f.Close()
2138		if f.Type != elf.ET_DYN {
2139			t.Errorf("PIE type must be ET_DYN, but %s", f.Type)
2140		}
2141	case "darwin":
2142		f, err := macho.Open(obj)
2143		if err != nil {
2144			t.Fatal(err)
2145		}
2146		defer f.Close()
2147		if f.Flags&macho.FlagDyldLink == 0 {
2148			t.Error("PIE must have DyldLink flag, but not")
2149		}
2150		if f.Flags&macho.FlagPIE == 0 {
2151			t.Error("PIE must have PIE flag, but not")
2152		}
2153	case "windows":
2154		f, err := pe.Open(obj)
2155		if err != nil {
2156			t.Fatal(err)
2157		}
2158		defer f.Close()
2159		if f.Section(".reloc") == nil {
2160			t.Error(".reloc section is not present")
2161		}
2162		if (f.FileHeader.Characteristics & pe.IMAGE_FILE_RELOCS_STRIPPED) != 0 {
2163			t.Error("IMAGE_FILE_RELOCS_STRIPPED flag is set")
2164		}
2165		var dc uint16
2166		switch oh := f.OptionalHeader.(type) {
2167		case *pe.OptionalHeader32:
2168			dc = oh.DllCharacteristics
2169		case *pe.OptionalHeader64:
2170			dc = oh.DllCharacteristics
2171			if (dc & pe.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) == 0 {
2172				t.Error("IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA flag is not set")
2173			}
2174		default:
2175			t.Fatalf("unexpected optional header type of %T", f.OptionalHeader)
2176		}
2177		if (dc & pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 {
2178			t.Error("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag is not set")
2179		}
2180		if useCgo {
2181			// Test that only one symbol is exported (#40795).
2182			// PIE binaries don´t require .edata section but unfortunately
2183			// binutils doesn´t generate a .reloc section unless there is
2184			// at least one symbol exported.
2185			// See https://sourceware.org/bugzilla/show_bug.cgi?id=19011
2186			section := f.Section(".edata")
2187			if section == nil {
2188				t.Skip(".edata section is not present")
2189			}
2190			// TODO: deduplicate this struct from cmd/link/internal/ld/pe.go
2191			type IMAGE_EXPORT_DIRECTORY struct {
2192				_                 [2]uint32
2193				_                 [2]uint16
2194				_                 [2]uint32
2195				NumberOfFunctions uint32
2196				NumberOfNames     uint32
2197				_                 [3]uint32
2198			}
2199			var e IMAGE_EXPORT_DIRECTORY
2200			if err := binary.Read(section.Open(), binary.LittleEndian, &e); err != nil {
2201				t.Fatalf("binary.Read failed: %v", err)
2202			}
2203
2204			// Only _cgo_dummy_export should be exported
2205			if e.NumberOfFunctions != 1 {
2206				t.Fatalf("got %d exported functions; want 1", e.NumberOfFunctions)
2207			}
2208			if e.NumberOfNames != 1 {
2209				t.Fatalf("got %d exported names; want 1", e.NumberOfNames)
2210			}
2211		}
2212	default:
2213		panic("unreachable")
2214	}
2215
2216	out, err := exec.Command(obj).CombinedOutput()
2217	if err != nil {
2218		t.Fatal(err)
2219	}
2220
2221	if string(out) != "hello" {
2222		t.Errorf("got %q; want %q", out, "hello")
2223	}
2224}
2225
2226func TestUpxCompression(t *testing.T) {
2227	if runtime.GOOS != "linux" ||
2228		(runtime.GOARCH != "amd64" && runtime.GOARCH != "386") {
2229		t.Skipf("skipping upx test on %s/%s", runtime.GOOS, runtime.GOARCH)
2230	}
2231
2232	testenv.MustHaveExecPath(t, "upx")
2233	out, err := exec.Command("upx", "--version").CombinedOutput()
2234	if err != nil {
2235		t.Fatalf("upx --version failed: %v", err)
2236	}
2237
2238	// upx --version prints `upx <version>` in the first line of output:
2239	//   upx 3.94
2240	//   [...]
2241	re := regexp.MustCompile(`([[:digit:]]+)\.([[:digit:]]+)`)
2242	upxVersion := re.FindStringSubmatch(string(out))
2243	if len(upxVersion) != 3 {
2244		t.Fatalf("bad upx version string: %s", upxVersion)
2245	}
2246
2247	major, err1 := strconv.Atoi(upxVersion[1])
2248	minor, err2 := strconv.Atoi(upxVersion[2])
2249	if err1 != nil || err2 != nil {
2250		t.Fatalf("bad upx version string: %s", upxVersion[0])
2251	}
2252
2253	// Anything below 3.94 is known not to work with go binaries
2254	if (major < 3) || (major == 3 && minor < 94) {
2255		t.Skipf("skipping because upx version %v.%v is too old", major, minor)
2256	}
2257
2258	tg := testgo(t)
2259	defer tg.cleanup()
2260	tg.parallel()
2261
2262	tg.tempFile("main.go", `package main; import "fmt"; func main() { fmt.Print("hello upx") }`)
2263	src := tg.path("main.go")
2264	obj := tg.path("main")
2265	tg.run("build", "-o", obj, src)
2266
2267	out, err = exec.Command("upx", obj).CombinedOutput()
2268	if err != nil {
2269		t.Logf("executing upx\n%s\n", out)
2270		t.Fatalf("upx failed with %v", err)
2271	}
2272
2273	out, err = exec.Command(obj).CombinedOutput()
2274	if err != nil {
2275		t.Logf("%s", out)
2276		t.Fatalf("running compressed go binary failed with error %s", err)
2277	}
2278	if string(out) != "hello upx" {
2279		t.Fatalf("bad output from compressed go binary:\ngot %q; want %q", out, "hello upx")
2280	}
2281}
2282
2283func TestCacheListStale(t *testing.T) {
2284	tooSlow(t)
2285	if godebug.Get("gocacheverify") == "1" {
2286		t.Skip("GODEBUG gocacheverify")
2287	}
2288	tg := testgo(t)
2289	defer tg.cleanup()
2290	tg.parallel()
2291	tg.makeTempdir()
2292	tg.setenv("GOCACHE", tg.path("cache"))
2293	tg.tempFile("gopath/src/p/p.go", "package p; import _ \"q\"; func F(){}\n")
2294	tg.tempFile("gopath/src/q/q.go", "package q; func F(){}\n")
2295	tg.tempFile("gopath/src/m/m.go", "package main; import _ \"q\"; func main(){}\n")
2296
2297	tg.setenv("GOPATH", tg.path("gopath"))
2298	tg.run("install", "p", "m")
2299	tg.run("list", "-f={{.ImportPath}} {{.Stale}}", "m", "q", "p")
2300	tg.grepStdout("^m false", "m should not be stale")
2301	tg.grepStdout("^q true", "q should be stale")
2302	tg.grepStdout("^p false", "p should not be stale")
2303}
2304
2305func TestCacheCoverage(t *testing.T) {
2306	tooSlow(t)
2307
2308	if godebug.Get("gocacheverify") == "1" {
2309		t.Skip("GODEBUG gocacheverify")
2310	}
2311
2312	tg := testgo(t)
2313	defer tg.cleanup()
2314	tg.parallel()
2315	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
2316	tg.makeTempdir()
2317
2318	tg.setenv("GOCACHE", tg.path("c1"))
2319	tg.run("test", "-cover", "-short", "strings")
2320	tg.run("test", "-cover", "-short", "math", "strings")
2321}
2322
2323func TestIssue22588(t *testing.T) {
2324	// Don't get confused by stderr coming from tools.
2325	tg := testgo(t)
2326	defer tg.cleanup()
2327	tg.parallel()
2328
2329	if _, err := os.Stat("/usr/bin/time"); err != nil {
2330		t.Skip(err)
2331	}
2332
2333	tg.run("list", "-f={{.Stale}}", "runtime")
2334	tg.run("list", "-toolexec=/usr/bin/time", "-f={{.Stale}}", "runtime")
2335	tg.grepStdout("false", "incorrectly reported runtime as stale")
2336}
2337
2338func TestIssue22531(t *testing.T) {
2339	tooSlow(t)
2340	if godebug.Get("gocacheverify") == "1" {
2341		t.Skip("GODEBUG gocacheverify")
2342	}
2343	tg := testgo(t)
2344	defer tg.cleanup()
2345	tg.parallel()
2346	tg.makeTempdir()
2347	tg.setenv("GOPATH", tg.tempdir)
2348	tg.setenv("GOCACHE", tg.path("cache"))
2349	tg.tempFile("src/m/main.go", "package main /* c1 */; func main() {}\n")
2350	tg.run("install", "-x", "m")
2351	tg.run("list", "-f", "{{.Stale}}", "m")
2352	tg.grepStdout("false", "reported m as stale after install")
2353	tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix))
2354
2355	// The link action ID did not include the full main build ID,
2356	// even though the full main build ID is written into the
2357	// eventual binary. That caused the following install to
2358	// be a no-op, thinking the gofmt binary was up-to-date,
2359	// even though .Stale could see it was not.
2360	tg.tempFile("src/m/main.go", "package main /* c2 */; func main() {}\n")
2361	tg.run("install", "-x", "m")
2362	tg.run("list", "-f", "{{.Stale}}", "m")
2363	tg.grepStdout("false", "reported m as stale after reinstall")
2364	tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix))
2365}
2366
2367func TestIssue22596(t *testing.T) {
2368	tooSlow(t)
2369	if godebug.Get("gocacheverify") == "1" {
2370		t.Skip("GODEBUG gocacheverify")
2371	}
2372	tg := testgo(t)
2373	defer tg.cleanup()
2374	tg.parallel()
2375	tg.makeTempdir()
2376	tg.setenv("GOCACHE", tg.path("cache"))
2377	tg.tempFile("gopath1/src/p/p.go", "package p; func F(){}\n")
2378	tg.tempFile("gopath2/src/p/p.go", "package p; func F(){}\n")
2379
2380	tg.setenv("GOPATH", tg.path("gopath1"))
2381	tg.run("list", "-f={{.Target}}", "p")
2382	target1 := strings.TrimSpace(tg.getStdout())
2383	tg.run("install", "p")
2384	tg.wantNotStale("p", "", "p stale after install")
2385
2386	tg.setenv("GOPATH", tg.path("gopath2"))
2387	tg.run("list", "-f={{.Target}}", "p")
2388	target2 := strings.TrimSpace(tg.getStdout())
2389	tg.must(os.MkdirAll(filepath.Dir(target2), 0777))
2390	tg.must(copyFile(target1, target2, 0666))
2391	tg.wantStale("p", "build ID mismatch", "p not stale after copy from gopath1")
2392	tg.run("install", "p")
2393	tg.wantNotStale("p", "", "p stale after install2")
2394}
2395
2396func TestTestCache(t *testing.T) {
2397	tooSlow(t)
2398
2399	if godebug.Get("gocacheverify") == "1" {
2400		t.Skip("GODEBUG gocacheverify")
2401	}
2402	tg := testgo(t)
2403	defer tg.cleanup()
2404	tg.parallel()
2405	tg.makeTempdir()
2406	tg.setenv("GOPATH", tg.tempdir)
2407	tg.setenv("GOCACHE", tg.path("cache"))
2408
2409	// The -p=1 in the commands below just makes the -x output easier to read.
2410
2411	t.Log("\n\nINITIAL\n\n")
2412
2413	tg.tempFile("src/p1/p1.go", "package p1\nvar X =  1\n")
2414	tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\nvar X = 1\n")
2415	tg.tempFile("src/t/t1/t1_test.go", "package t\nimport \"testing\"\nfunc Test1(*testing.T) {}\n")
2416	tg.tempFile("src/t/t2/t2_test.go", "package t\nimport _ \"p1\"\nimport \"testing\"\nfunc Test2(*testing.T) {}\n")
2417	tg.tempFile("src/t/t3/t3_test.go", "package t\nimport \"p1\"\nimport \"testing\"\nfunc Test3(t *testing.T) {t.Log(p1.X)}\n")
2418	tg.tempFile("src/t/t4/t4_test.go", "package t\nimport \"p2\"\nimport \"testing\"\nfunc Test4(t *testing.T) {t.Log(p2.X)}")
2419	tg.run("test", "-x", "-v", "-short", "t/...")
2420
2421	t.Log("\n\nREPEAT\n\n")
2422
2423	tg.run("test", "-x", "-v", "-short", "t/...")
2424	tg.grepStdout(`ok  \tt/t1\t\(cached\)`, "did not cache t1")
2425	tg.grepStdout(`ok  \tt/t2\t\(cached\)`, "did not cache t2")
2426	tg.grepStdout(`ok  \tt/t3\t\(cached\)`, "did not cache t3")
2427	tg.grepStdout(`ok  \tt/t4\t\(cached\)`, "did not cache t4")
2428	tg.grepStderrNot(`[\\/](compile|gccgo) `, "incorrectly ran compiler")
2429	tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker")
2430	tg.grepStderrNot(`p[0-9]\.test`, "incorrectly ran test")
2431
2432	t.Log("\n\nCOMMENT\n\n")
2433
2434	// Changing the program text without affecting the compiled package
2435	// should result in the package being rebuilt but nothing more.
2436	tg.tempFile("src/p1/p1.go", "package p1\nvar X = 01\n")
2437	tg.run("test", "-p=1", "-x", "-v", "-short", "t/...")
2438	tg.grepStdout(`ok  \tt/t1\t\(cached\)`, "did not cache t1")
2439	tg.grepStdout(`ok  \tt/t2\t\(cached\)`, "did not cache t2")
2440	tg.grepStdout(`ok  \tt/t3\t\(cached\)`, "did not cache t3")
2441	tg.grepStdout(`ok  \tt/t4\t\(cached\)`, "did not cache t4")
2442	tg.grepStderrNot(`([\\/](compile|gccgo) ).*t[0-9]_test\.go`, "incorrectly ran compiler")
2443	tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker")
2444	tg.grepStderrNot(`t[0-9]\.test.*test\.short`, "incorrectly ran test")
2445
2446	t.Log("\n\nCHANGE\n\n")
2447
2448	// Changing the actual package should have limited effects.
2449	tg.tempFile("src/p1/p1.go", "package p1\nvar X = 02\n")
2450	tg.run("test", "-p=1", "-x", "-v", "-short", "t/...")
2451
2452	// p2 should have been rebuilt.
2453	tg.grepStderr(`([\\/]compile|gccgo).*p2.go`, "did not recompile p2")
2454
2455	// t1 does not import anything, should not have been rebuilt.
2456	tg.grepStderrNot(`([\\/]compile|gccgo).*t1_test.go`, "incorrectly recompiled t1")
2457	tg.grepStderrNot(`([\\/]link|gccgo).*t1_test`, "incorrectly relinked t1_test")
2458	tg.grepStdout(`ok  \tt/t1\t\(cached\)`, "did not cache t/t1")
2459
2460	// t2 imports p1 and must be rebuilt and relinked,
2461	// but the change should not have any effect on the test binary,
2462	// so the test should not have been rerun.
2463	tg.grepStderr(`([\\/]compile|gccgo).*t2_test.go`, "did not recompile t2")
2464	tg.grepStderr(`([\\/]link|gccgo).*t2\.test`, "did not relink t2_test")
2465	// This check does not currently work with gccgo, as garbage
2466	// collection of unused variables is not turned on by default.
2467	if runtime.Compiler != "gccgo" {
2468		tg.grepStdout(`ok  \tt/t2\t\(cached\)`, "did not cache t/t2")
2469	}
2470
2471	// t3 imports p1, and changing X changes t3's test binary.
2472	tg.grepStderr(`([\\/]compile|gccgo).*t3_test.go`, "did not recompile t3")
2473	tg.grepStderr(`([\\/]link|gccgo).*t3\.test`, "did not relink t3_test")
2474	tg.grepStderr(`t3\.test.*-test.short`, "did not rerun t3_test")
2475	tg.grepStdoutNot(`ok  \tt/t3\t\(cached\)`, "reported cached t3_test result")
2476
2477	// t4 imports p2, but p2 did not change, so t4 should be relinked, not recompiled,
2478	// and not rerun.
2479	tg.grepStderrNot(`([\\/]compile|gccgo).*t4_test.go`, "incorrectly recompiled t4")
2480	tg.grepStderr(`([\\/]link|gccgo).*t4\.test`, "did not relink t4_test")
2481	// This check does not currently work with gccgo, as garbage
2482	// collection of unused variables is not turned on by default.
2483	if runtime.Compiler != "gccgo" {
2484		tg.grepStdout(`ok  \tt/t4\t\(cached\)`, "did not cache t/t4")
2485	}
2486}
2487
2488func TestTestSkipVetAfterFailedBuild(t *testing.T) {
2489	tg := testgo(t)
2490	defer tg.cleanup()
2491	tg.parallel()
2492
2493	tg.tempFile("x_test.go", `package x
2494		func f() {
2495			return 1
2496		}
2497	`)
2498
2499	tg.runFail("test", tg.path("x_test.go"))
2500	tg.grepStderrNot(`vet`, "vet should be skipped after the failed build")
2501}
2502
2503func TestTestVetRebuild(t *testing.T) {
2504	tooSlow(t)
2505	tg := testgo(t)
2506	defer tg.cleanup()
2507	tg.parallel()
2508
2509	// golang.org/issue/23701.
2510	// b_test imports b with augmented method from export_test.go.
2511	// b_test also imports a, which imports b.
2512	// Must not accidentally see un-augmented b propagate through a to b_test.
2513	tg.tempFile("src/a/a.go", `package a
2514		import "b"
2515		type Type struct{}
2516		func (*Type) M() b.T {return 0}
2517	`)
2518	tg.tempFile("src/b/b.go", `package b
2519		type T int
2520		type I interface {M() T}
2521	`)
2522	tg.tempFile("src/b/export_test.go", `package b
2523		func (*T) Method() *T { return nil }
2524	`)
2525	tg.tempFile("src/b/b_test.go", `package b_test
2526		import (
2527			"testing"
2528			"a"
2529			. "b"
2530		)
2531		func TestBroken(t *testing.T) {
2532			x := new(T)
2533			x.Method()
2534			_ = new(a.Type)
2535		}
2536	`)
2537
2538	tg.setenv("GOPATH", tg.path("."))
2539	tg.run("test", "b")
2540	tg.run("vet", "b")
2541}
2542
2543func TestInstallDeps(t *testing.T) {
2544	tooSlow(t)
2545	tg := testgo(t)
2546	defer tg.cleanup()
2547	tg.parallel()
2548	tg.makeTempdir()
2549	tg.setenv("GOPATH", tg.tempdir)
2550
2551	tg.tempFile("src/p1/p1.go", "package p1\nvar X =  1\n")
2552	tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\n")
2553	tg.tempFile("src/main1/main.go", "package main\nimport _ \"p2\"\nfunc main() {}\n")
2554
2555	tg.run("list", "-f={{.Target}}", "p1")
2556	p1 := strings.TrimSpace(tg.getStdout())
2557	tg.run("list", "-f={{.Target}}", "p2")
2558	p2 := strings.TrimSpace(tg.getStdout())
2559	tg.run("list", "-f={{.Target}}", "main1")
2560	main1 := strings.TrimSpace(tg.getStdout())
2561
2562	tg.run("install", "main1")
2563
2564	tg.mustExist(main1)
2565	tg.mustNotExist(p2)
2566	tg.mustNotExist(p1)
2567
2568	tg.run("install", "p2")
2569	tg.mustExist(p2)
2570	tg.mustNotExist(p1)
2571
2572	// don't let install -i overwrite runtime
2573	tg.wantNotStale("runtime", "", "must be non-stale before install -i")
2574
2575	tg.run("install", "-i", "main1")
2576	tg.mustExist(p1)
2577	tg.must(os.Remove(p1))
2578
2579	tg.run("install", "-i", "p2")
2580	tg.mustExist(p1)
2581}
2582
2583// Issue 22986.
2584func TestImportPath(t *testing.T) {
2585	tooSlow(t)
2586	tg := testgo(t)
2587	defer tg.cleanup()
2588	tg.parallel()
2589
2590	tg.tempFile("src/a/a.go", `
2591package main
2592
2593import (
2594	"log"
2595	p "a/p-1.0"
2596)
2597
2598func main() {
2599	if !p.V {
2600		log.Fatal("false")
2601	}
2602}`)
2603
2604	tg.tempFile("src/a/a_test.go", `
2605package main_test
2606
2607import (
2608	p "a/p-1.0"
2609	"testing"
2610)
2611
2612func TestV(t *testing.T) {
2613	if !p.V {
2614		t.Fatal("false")
2615	}
2616}`)
2617
2618	tg.tempFile("src/a/p-1.0/p.go", `
2619package p
2620
2621var V = true
2622
2623func init() {}
2624`)
2625
2626	tg.setenv("GOPATH", tg.path("."))
2627	tg.run("build", "-o", tg.path("a.exe"), "a")
2628	tg.run("test", "a")
2629}
2630
2631func TestBadCommandLines(t *testing.T) {
2632	tg := testgo(t)
2633	defer tg.cleanup()
2634	tg.parallel()
2635
2636	tg.tempFile("src/x/x.go", "package x\n")
2637	tg.setenv("GOPATH", tg.path("."))
2638
2639	tg.run("build", "x")
2640
2641	tg.tempFile("src/x/@y.go", "package x\n")
2642	tg.runFail("build", "x")
2643	tg.grepStderr("invalid input file name \"@y.go\"", "did not reject @y.go")
2644	tg.must(os.Remove(tg.path("src/x/@y.go")))
2645
2646	tg.tempFile("src/x/-y.go", "package x\n")
2647	tg.runFail("build", "x")
2648	tg.grepStderr("invalid input file name \"-y.go\"", "did not reject -y.go")
2649	tg.must(os.Remove(tg.path("src/x/-y.go")))
2650
2651	if runtime.Compiler == "gccgo" {
2652		tg.runFail("build", "-gccgoflags=all=@x", "x")
2653	} else {
2654		tg.runFail("build", "-gcflags=all=@x", "x")
2655	}
2656	tg.grepStderr("invalid command-line argument @x in command", "did not reject @x during exec")
2657
2658	tg.tempFile("src/@x/x.go", "package x\n")
2659	tg.setenv("GOPATH", tg.path("."))
2660	tg.runFail("build", "@x")
2661	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")
2662
2663	tg.tempFile("src/@x/y/y.go", "package y\n")
2664	tg.setenv("GOPATH", tg.path("."))
2665	tg.runFail("build", "@x/y")
2666	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")
2667
2668	tg.tempFile("src/-x/x.go", "package x\n")
2669	tg.setenv("GOPATH", tg.path("."))
2670	tg.runFail("build", "--", "-x")
2671	tg.grepStderr("invalid import path \"-x\"", "did not reject -x import path")
2672
2673	tg.tempFile("src/-x/y/y.go", "package y\n")
2674	tg.setenv("GOPATH", tg.path("."))
2675	tg.runFail("build", "--", "-x/y")
2676	tg.grepStderr("invalid import path \"-x/y\"", "did not reject -x/y import path")
2677}
2678
2679func TestTwoPkgConfigs(t *testing.T) {
2680	if !canCgo {
2681		t.Skip("no cgo")
2682	}
2683	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
2684		t.Skipf("no shell scripts on %s", runtime.GOOS)
2685	}
2686	tooSlow(t)
2687	tg := testgo(t)
2688	defer tg.cleanup()
2689	tg.parallel()
2690	tg.tempFile("src/x/a.go", `package x
2691		// #cgo pkg-config: --static a
2692		import "C"
2693	`)
2694	tg.tempFile("src/x/b.go", `package x
2695		// #cgo pkg-config: --static a
2696		import "C"
2697	`)
2698	tg.tempFile("pkg-config.sh", `#!/bin/sh
2699echo $* >>`+tg.path("pkg-config.out"))
2700	tg.must(os.Chmod(tg.path("pkg-config.sh"), 0755))
2701	tg.setenv("GOPATH", tg.path("."))
2702	tg.setenv("PKG_CONFIG", tg.path("pkg-config.sh"))
2703	tg.run("build", "x")
2704	out, err := os.ReadFile(tg.path("pkg-config.out"))
2705	tg.must(err)
2706	out = bytes.TrimSpace(out)
2707	want := "--cflags --static --static -- a a\n--libs --static --static -- a a"
2708	if !bytes.Equal(out, []byte(want)) {
2709		t.Errorf("got %q want %q", out, want)
2710	}
2711}
2712
2713func TestCgoCache(t *testing.T) {
2714	if !canCgo {
2715		t.Skip("no cgo")
2716	}
2717	tooSlow(t)
2718
2719	tg := testgo(t)
2720	defer tg.cleanup()
2721	tg.parallel()
2722	tg.tempFile("src/x/a.go", `package main
2723		// #ifndef VAL
2724		// #define VAL 0
2725		// #endif
2726		// int val = VAL;
2727		import "C"
2728		import "fmt"
2729		func main() { fmt.Println(C.val) }
2730	`)
2731	tg.setenv("GOPATH", tg.path("."))
2732	exe := tg.path("x.exe")
2733	tg.run("build", "-o", exe, "x")
2734	tg.setenv("CGO_LDFLAGS", "-lnosuchlibraryexists")
2735	tg.runFail("build", "-o", exe, "x")
2736	tg.grepStderr(`nosuchlibraryexists`, "did not run linker with changed CGO_LDFLAGS")
2737}
2738
2739// Issue 23982
2740func TestFilepathUnderCwdFormat(t *testing.T) {
2741	tg := testgo(t)
2742	defer tg.cleanup()
2743	tg.parallel()
2744	tg.run("test", "-x", "-cover", "log")
2745	tg.grepStderrNot(`\.log\.cover\.go`, "-x output should contain correctly formatted filepath under cwd")
2746}
2747
2748// Issue 24396.
2749func TestDontReportRemoveOfEmptyDir(t *testing.T) {
2750	tg := testgo(t)
2751	defer tg.cleanup()
2752	tg.parallel()
2753	tg.tempFile("src/a/a.go", `package a`)
2754	tg.setenv("GOPATH", tg.path("."))
2755	tg.run("install", "-x", "a")
2756	tg.run("install", "-x", "a")
2757	// The second install should have printed only a WORK= line,
2758	// nothing else.
2759	if bytes.Count(tg.stdout.Bytes(), []byte{'\n'})+bytes.Count(tg.stderr.Bytes(), []byte{'\n'}) > 1 {
2760		t.Error("unnecessary output when installing installed package")
2761	}
2762}
2763
2764// Issue 24704.
2765func TestLinkerTmpDirIsDeleted(t *testing.T) {
2766	skipIfGccgo(t, "gccgo does not use cmd/link")
2767	if !canCgo {
2768		t.Skip("skipping because cgo not enabled")
2769	}
2770	tooSlow(t)
2771
2772	tg := testgo(t)
2773	defer tg.cleanup()
2774	tg.parallel()
2775	tg.tempFile("a.go", `package main; import "C"; func main() {}`)
2776	tg.run("build", "-ldflags", "-v", "-o", os.DevNull, tg.path("a.go"))
2777	// Find line that has "host link:" in linker output.
2778	stderr := tg.getStderr()
2779	var hostLinkLine string
2780	for _, line := range strings.Split(stderr, "\n") {
2781		if !strings.Contains(line, "host link:") {
2782			continue
2783		}
2784		hostLinkLine = line
2785		break
2786	}
2787	if hostLinkLine == "" {
2788		t.Fatal(`fail to find with "host link:" string in linker output`)
2789	}
2790	// Find parameter, like "/tmp/go-link-408556474/go.o" inside of
2791	// "host link:" line, and extract temp directory /tmp/go-link-408556474
2792	// out of it.
2793	tmpdir := hostLinkLine
2794	i := strings.Index(tmpdir, `go.o"`)
2795	if i == -1 {
2796		t.Fatalf(`fail to find "go.o" in "host link:" line %q`, hostLinkLine)
2797	}
2798	tmpdir = tmpdir[:i-1]
2799	i = strings.LastIndex(tmpdir, `"`)
2800	if i == -1 {
2801		t.Fatalf(`fail to find " in "host link:" line %q`, hostLinkLine)
2802	}
2803	tmpdir = tmpdir[i+1:]
2804	// Verify that temp directory has been removed.
2805	_, err := os.Stat(tmpdir)
2806	if err == nil {
2807		t.Fatalf("temp directory %q has not been removed", tmpdir)
2808	}
2809	if !os.IsNotExist(err) {
2810		t.Fatalf("Stat(%q) returns unexpected error: %v", tmpdir, err)
2811	}
2812}
2813
2814// Issue 25093.
2815func TestCoverpkgTestOnly(t *testing.T) {
2816	skipIfGccgo(t, "gccgo has no cover tool")
2817	tooSlow(t)
2818	tg := testgo(t)
2819	defer tg.cleanup()
2820	tg.parallel()
2821	tg.tempFile("src/a/a.go", `package a
2822		func F(i int) int {
2823			return i*i
2824		}`)
2825	tg.tempFile("src/atest/a_test.go", `
2826		package a_test
2827		import ( "a"; "testing" )
2828		func TestF(t *testing.T) { a.F(2) }
2829	`)
2830	tg.setenv("GOPATH", tg.path("."))
2831	tg.run("test", "-coverpkg=a", "atest")
2832	tg.grepStderrNot("no packages being tested depend on matches", "bad match message")
2833	tg.grepStdout("coverage: 100", "no coverage")
2834}
2835
2836// Regression test for golang.org/issue/34499: version command should not crash
2837// when executed in a deleted directory on Linux.
2838func TestExecInDeletedDir(t *testing.T) {
2839	switch runtime.GOOS {
2840	case "windows", "plan9",
2841		"aix",                // Fails with "device busy".
2842		"solaris", "illumos": // Fails with "invalid argument".
2843		t.Skipf("%v does not support removing the current working directory", runtime.GOOS)
2844	}
2845	tg := testgo(t)
2846	defer tg.cleanup()
2847
2848	wd, err := os.Getwd()
2849	tg.check(err)
2850	tg.makeTempdir()
2851	tg.check(os.Chdir(tg.tempdir))
2852	defer func() { tg.check(os.Chdir(wd)) }()
2853
2854	tg.check(os.Remove(tg.tempdir))
2855
2856	// `go version` should not fail
2857	tg.run("version")
2858}
2859
2860// A missing C compiler should not force the net package to be stale.
2861// Issue 47215.
2862func TestMissingCC(t *testing.T) {
2863	if !canCgo {
2864		t.Skip("test is only meaningful on systems with cgo")
2865	}
2866	cc := os.Getenv("CC")
2867	if cc == "" {
2868		cc = "gcc"
2869	}
2870	if filepath.IsAbs(cc) {
2871		t.Skipf(`"CC" (%s) is an absolute path`, cc)
2872	}
2873	_, err := exec.LookPath(cc)
2874	if err != nil {
2875		t.Skipf(`"CC" (%s) not on PATH`, cc)
2876	}
2877
2878	tg := testgo(t)
2879	defer tg.cleanup()
2880	netStale, _ := tg.isStale("net")
2881	if netStale {
2882		t.Skip(`skipping test because "net" package is currently stale`)
2883	}
2884
2885	tg.setenv("PATH", "") // No C compiler on PATH.
2886	netStale, _ = tg.isStale("net")
2887	if netStale {
2888		t.Error(`clearing "PATH" causes "net" to be stale`)
2889	}
2890}
2891