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