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 tg.t.Fatal("all tests using testgoData must run in parallel")
492 }
493 for _, arg := range args {
494 if strings.HasPrefix(arg, "testdata") || strings.HasPrefix(arg, "./testdata") {
495 tg.t.Fatal("internal testsuite error: parallel run using testdata")
496 }
497 }
498
499 hasGoroot := false
500 for _, v := range tg.env {
501 if strings.HasPrefix(v, "GOROOT=") {
502 hasGoroot = true
503 break
504 }
505 }
506 prog := tg.goTool()
507 if !hasGoroot {
508 tg.setenv("GOROOT", testGOROOT)
509 }
510
511 tg.t.Logf("running testgo %v", args)
512 cmd := testenv.Command(tg.t, prog, args...)
513 tg.stdout.Reset()
514 tg.stderr.Reset()
515 cmd.Dir = tg.execDir
516 cmd.Stdout = &tg.stdout
517 cmd.Stderr = &tg.stderr
518 cmd.Env = tg.env
519 status := cmd.Run()
520 if tg.stdout.Len() > 0 {
521 tg.t.Log("standard output:")
522 tg.t.Log(tg.stdout.String())
523 }
524 if tg.stderr.Len() > 0 {
525 tg.t.Log("standard error:")
526 tg.t.Log(tg.stderr.String())
527 }
528 tg.ran = true
529 return status
530 }
531
532
533 func (tg *testgoData) run(args ...string) {
534 tg.t.Helper()
535 if status := tg.doRun(args); status != nil {
536 wd, _ := os.Getwd()
537 tg.t.Logf("go %v failed unexpectedly in %s: %v", args, wd, status)
538 tg.t.FailNow()
539 }
540 }
541
542
543 func (tg *testgoData) runFail(args ...string) {
544 tg.t.Helper()
545 if status := tg.doRun(args); status == nil {
546 tg.t.Fatal("testgo succeeded unexpectedly")
547 } else {
548 tg.t.Log("testgo failed as expected:", status)
549 }
550 }
551
552
553 func (tg *testgoData) getStdout() string {
554 tg.t.Helper()
555 if !tg.ran {
556 tg.t.Fatal("internal testsuite error: stdout called before run")
557 }
558 return tg.stdout.String()
559 }
560
561
562 func (tg *testgoData) getStderr() string {
563 tg.t.Helper()
564 if !tg.ran {
565 tg.t.Fatal("internal testsuite error: stdout called before run")
566 }
567 return tg.stderr.String()
568 }
569
570
571
572
573 func (tg *testgoData) doGrepMatch(match string, b *bytes.Buffer) bool {
574 tg.t.Helper()
575 if !tg.ran {
576 tg.t.Fatal("internal testsuite error: grep called before run")
577 }
578 re := regexp.MustCompile(match)
579 for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) {
580 if re.Match(ln) {
581 return true
582 }
583 }
584 return false
585 }
586
587
588
589
590
591 func (tg *testgoData) doGrep(match string, b *bytes.Buffer, name, msg string) {
592 tg.t.Helper()
593 if !tg.doGrepMatch(match, b) {
594 tg.t.Log(msg)
595 tg.t.Logf("pattern %v not found in standard %s", match, name)
596 tg.t.FailNow()
597 }
598 }
599
600
601
602 func (tg *testgoData) grepStdout(match, msg string) {
603 tg.t.Helper()
604 tg.doGrep(match, &tg.stdout, "output", msg)
605 }
606
607
608
609 func (tg *testgoData) grepStderr(match, msg string) {
610 tg.t.Helper()
611 tg.doGrep(match, &tg.stderr, "error", msg)
612 }
613
614
615
616 func (tg *testgoData) grepBoth(match, msg string) {
617 tg.t.Helper()
618 if !tg.doGrepMatch(match, &tg.stdout) && !tg.doGrepMatch(match, &tg.stderr) {
619 tg.t.Log(msg)
620 tg.t.Logf("pattern %v not found in standard output or standard error", match)
621 tg.t.FailNow()
622 }
623 }
624
625
626
627 func (tg *testgoData) doGrepNot(match string, b *bytes.Buffer, name, msg string) {
628 tg.t.Helper()
629 if tg.doGrepMatch(match, b) {
630 tg.t.Log(msg)
631 tg.t.Logf("pattern %v found unexpectedly in standard %s", match, name)
632 tg.t.FailNow()
633 }
634 }
635
636
637
638 func (tg *testgoData) grepStdoutNot(match, msg string) {
639 tg.t.Helper()
640 tg.doGrepNot(match, &tg.stdout, "output", msg)
641 }
642
643
644
645 func (tg *testgoData) grepStderrNot(match, msg string) {
646 tg.t.Helper()
647 tg.doGrepNot(match, &tg.stderr, "error", msg)
648 }
649
650
651
652
653 func (tg *testgoData) grepBothNot(match, msg string) {
654 tg.t.Helper()
655 if tg.doGrepMatch(match, &tg.stdout) || tg.doGrepMatch(match, &tg.stderr) {
656 tg.t.Log(msg)
657 tg.t.Fatalf("pattern %v found unexpectedly in standard output or standard error", match)
658 }
659 }
660
661
662 func (tg *testgoData) doGrepCount(match string, b *bytes.Buffer) int {
663 tg.t.Helper()
664 if !tg.ran {
665 tg.t.Fatal("internal testsuite error: doGrepCount called before run")
666 }
667 re := regexp.MustCompile(match)
668 c := 0
669 for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) {
670 if re.Match(ln) {
671 c++
672 }
673 }
674 return c
675 }
676
677
678
679 func (tg *testgoData) grepCountBoth(match string) int {
680 tg.t.Helper()
681 return tg.doGrepCount(match, &tg.stdout) + tg.doGrepCount(match, &tg.stderr)
682 }
683
684
685
686
687
688 func (tg *testgoData) creatingTemp(path string) {
689 tg.t.Helper()
690 if filepath.IsAbs(path) && !strings.HasPrefix(path, tg.tempdir) {
691 tg.t.Fatalf("internal testsuite error: creatingTemp(%q) with absolute path not in temporary directory", path)
692 }
693 tg.must(robustio.RemoveAll(path))
694 tg.temps = append(tg.temps, path)
695 }
696
697
698
699 func (tg *testgoData) makeTempdir() {
700 tg.t.Helper()
701 if tg.tempdir == "" {
702 var err error
703 tg.tempdir, err = os.MkdirTemp("", "gotest")
704 tg.must(err)
705 }
706 }
707
708
709 func (tg *testgoData) tempFile(path, contents string) {
710 tg.t.Helper()
711 tg.makeTempdir()
712 tg.must(os.MkdirAll(filepath.Join(tg.tempdir, filepath.Dir(path)), 0755))
713 bytes := []byte(contents)
714 if strings.HasSuffix(path, ".go") {
715 formatted, err := format.Source(bytes)
716 if err == nil {
717 bytes = formatted
718 }
719 }
720 tg.must(os.WriteFile(filepath.Join(tg.tempdir, path), bytes, 0644))
721 }
722
723
724 func (tg *testgoData) tempDir(path string) {
725 tg.t.Helper()
726 tg.makeTempdir()
727 if err := os.MkdirAll(filepath.Join(tg.tempdir, path), 0755); err != nil && !os.IsExist(err) {
728 tg.t.Fatal(err)
729 }
730 }
731
732
733
734 func (tg *testgoData) path(name string) string {
735 tg.t.Helper()
736 if tg.tempdir == "" {
737 tg.t.Fatalf("internal testsuite error: path(%q) with no tempdir", name)
738 }
739 if name == "." {
740 return tg.tempdir
741 }
742 return filepath.Join(tg.tempdir, name)
743 }
744
745
746 func (tg *testgoData) mustExist(path string) {
747 tg.t.Helper()
748 if _, err := os.Stat(path); err != nil {
749 if os.IsNotExist(err) {
750 tg.t.Fatalf("%s does not exist but should", path)
751 }
752 tg.t.Fatalf("%s stat failed: %v", path, err)
753 }
754 }
755
756
757 func (tg *testgoData) mustNotExist(path string) {
758 tg.t.Helper()
759 if _, err := os.Stat(path); err == nil || !os.IsNotExist(err) {
760 tg.t.Fatalf("%s exists but should not (%v)", path, err)
761 }
762 }
763
764
765 func (tg *testgoData) wantExecutable(path, msg string) {
766 tg.t.Helper()
767 if st, err := os.Stat(path); err != nil {
768 if !os.IsNotExist(err) {
769 tg.t.Log(err)
770 }
771 tg.t.Fatal(msg)
772 } else {
773 if runtime.GOOS != "windows" && st.Mode()&0111 == 0 {
774 tg.t.Fatalf("binary %s exists but is not executable", path)
775 }
776 }
777 }
778
779
780 func (tg *testgoData) isStale(pkg string) (bool, string) {
781 tg.t.Helper()
782 tg.run("list", "-f", "{{.Stale}}:{{.StaleReason}}", pkg)
783 v := strings.TrimSpace(tg.getStdout())
784 f := strings.SplitN(v, ":", 2)
785 if len(f) == 2 {
786 switch f[0] {
787 case "true":
788 return true, f[1]
789 case "false":
790 return false, f[1]
791 }
792 }
793 tg.t.Fatalf("unexpected output checking staleness of package %v: %v", pkg, v)
794 panic("unreachable")
795 }
796
797
798 func (tg *testgoData) wantStale(pkg, reason, msg string) {
799 tg.t.Helper()
800 stale, why := tg.isStale(pkg)
801 if !stale {
802 tg.t.Fatal(msg)
803 }
804
805
806
807
808 if reason == "" && why != "" || !strings.Contains(why, reason) && !strings.Contains(why, "not installed but available in build cache") {
809 tg.t.Errorf("wrong reason for Stale=true: %q, want %q", why, reason)
810 }
811 }
812
813
814 func (tg *testgoData) wantNotStale(pkg, reason, msg string) {
815 tg.t.Helper()
816 stale, why := tg.isStale(pkg)
817 if stale {
818 tg.t.Fatal(msg)
819 }
820 if reason == "" && why != "" || !strings.Contains(why, reason) {
821 tg.t.Errorf("wrong reason for Stale=false: %q, want %q", why, reason)
822 }
823 }
824
825
826
827
828 var testWork = flag.Bool("testwork", false, "")
829
830
831 func (tg *testgoData) cleanup() {
832 tg.t.Helper()
833 if *testWork {
834 if tg.tempdir != "" {
835 tg.t.Logf("TESTWORK=%s\n", tg.path("."))
836 }
837 return
838 }
839 for _, path := range tg.temps {
840 tg.check(removeAll(path))
841 }
842 if tg.tempdir != "" {
843 tg.check(removeAll(tg.tempdir))
844 }
845 }
846
847 func removeAll(dir string) error {
848
849
850 filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error {
851
852
853 if err != nil || info.IsDir() {
854 os.Chmod(path, 0777)
855 }
856 return nil
857 })
858 return robustio.RemoveAll(dir)
859 }
860
861 func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
862 if testing.Short() {
863 t.Skip("skipping lengthy test in short mode")
864 }
865
866 tg := testgo(t)
867 defer tg.cleanup()
868 tg.parallel()
869
870
871
872 tg.tempDir("gocache")
873 tg.setenv("GOCACHE", tg.path("gocache"))
874
875
876
877 var dirs []string
878 tg.run("list", "-deps", "runtime")
879 pkgs := strings.Split(strings.TrimSpace(tg.getStdout()), "\n")
880 for _, pkg := range pkgs {
881 dirs = append(dirs, filepath.Join("src", pkg))
882 }
883 dirs = append(dirs,
884 filepath.Join("pkg/tool", goHostOS+"_"+goHostArch),
885 "pkg/include",
886 )
887 for _, copydir := range dirs {
888 srcdir := filepath.Join(testGOROOT, copydir)
889 tg.tempDir(filepath.Join("goroot", copydir))
890 err := filepath.WalkDir(srcdir,
891 func(path string, info fs.DirEntry, err error) error {
892 if err != nil {
893 return err
894 }
895 if info.IsDir() {
896 return nil
897 }
898 srcrel, err := filepath.Rel(srcdir, path)
899 if err != nil {
900 return err
901 }
902 dest := filepath.Join("goroot", copydir, srcrel)
903 if _, err := os.Stat(dest); err == nil {
904 return nil
905 }
906 data, err := os.ReadFile(path)
907 if err != nil {
908 return err
909 }
910 tg.tempFile(dest, string(data))
911 if strings.Contains(copydir, filepath.Join("pkg", "tool")) {
912 os.Chmod(tg.path(dest), 0777)
913 }
914 return nil
915 })
916 if err != nil {
917 t.Fatal(err)
918 }
919 }
920 tg.setenv("GOROOT", tg.path("goroot"))
921
922 addVar := func(name string, idx int) (restore func()) {
923 data, err := os.ReadFile(name)
924 if err != nil {
925 t.Fatal(err)
926 }
927 old := data
928 data = append(data, fmt.Sprintf("var DummyUnusedVar%d bool\n", idx)...)
929 if err := os.WriteFile(name, append(data, '\n'), 0666); err != nil {
930 t.Fatal(err)
931 }
932 tg.sleep()
933 return func() {
934 if err := os.WriteFile(name, old, 0666); err != nil {
935 t.Fatal(err)
936 }
937 }
938 }
939
940
941 tg.tempFile("d1/src/p1/p1.go", `package main; func main(){}`)
942 tg.setenv("GOPATH", tg.path("d1"))
943
944 tg.run("install", "p1")
945 tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, before any changes")
946
947
948
949
950 sys := tg.path("goroot/src/internal/runtime/sys/sys.go")
951 tg.sleep()
952 restore := addVar(sys, 0)
953 restore()
954 tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after updating mtime of internal/runtime/sys/sys.go")
955
956
957
958
959 restore = addVar(sys, 1)
960 defer restore()
961 tg.wantStale("p1", "stale dependency: internal/runtime/sys", "./testgo list claims p1 is NOT stale, incorrectly, after changing sys.go")
962 restore()
963 tg.wantNotStale("p1", "", "./testgo list claims p1 is stale, incorrectly, after changing back to old release")
964 addVar(sys, 2)
965 tg.wantStale("p1", "stale dependency: internal/runtime/sys", "./testgo list claims p1 is NOT stale, incorrectly, after changing sys.go again")
966 tg.run("install", "p1")
967 tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with new release")
968
969
970 restore()
971 tg.wantStale("p1", "not installed but available in build cache", "./testgo list claims p1 is NOT stale, incorrectly, after restoring sys.go")
972 tg.run("install", "p1")
973 tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with old release")
974 }
975
976
977 func TestGoTestWithPackageListedMultipleTimes(t *testing.T) {
978 tooSlow(t, "links and runs a test")
979
980 tg := testgo(t)
981 defer tg.cleanup()
982 tg.parallel()
983 tg.run("test", "errors", "errors", "errors", "errors", "errors")
984 if strings.Contains(strings.TrimSpace(tg.getStdout()), "\n") {
985 t.Error("go test errors errors errors errors errors tested the same package multiple times")
986 }
987 }
988
989 func TestGoListHasAConsistentOrder(t *testing.T) {
990 tooSlow(t, "walks all of GOROOT/src twice")
991
992 tg := testgo(t)
993 defer tg.cleanup()
994 tg.parallel()
995 tg.run("list", "std")
996 first := tg.getStdout()
997 tg.run("list", "std")
998 if first != tg.getStdout() {
999 t.Error("go list std ordering is inconsistent")
1000 }
1001 }
1002
1003 func TestGoListStdDoesNotIncludeCommands(t *testing.T) {
1004 tooSlow(t, "walks all of GOROOT/src")
1005
1006 tg := testgo(t)
1007 defer tg.cleanup()
1008 tg.parallel()
1009 tg.run("list", "std")
1010 tg.grepStdoutNot("cmd/", "go list std shows commands")
1011 }
1012
1013 func TestGoListCmdOnlyShowsCommands(t *testing.T) {
1014 skipIfGccgo(t, "gccgo does not have GOROOT")
1015 tooSlow(t, "walks all of GOROOT/src/cmd")
1016
1017 tg := testgo(t)
1018 defer tg.cleanup()
1019 tg.parallel()
1020 tg.run("list", "cmd")
1021 out := strings.TrimSpace(tg.getStdout())
1022 for _, line := range strings.Split(out, "\n") {
1023 if !strings.Contains(line, "cmd/") {
1024 t.Error("go list cmd shows non-commands")
1025 break
1026 }
1027 }
1028 }
1029
1030 func TestGoListDeps(t *testing.T) {
1031 tg := testgo(t)
1032 defer tg.cleanup()
1033 tg.parallel()
1034 tg.tempDir("src/p1/p2/p3/p4")
1035 tg.setenv("GOPATH", tg.path("."))
1036 tg.tempFile("src/p1/p.go", "package p1\nimport _ \"p1/p2\"\n")
1037 tg.tempFile("src/p1/p2/p.go", "package p2\nimport _ \"p1/p2/p3\"\n")
1038 tg.tempFile("src/p1/p2/p3/p.go", "package p3\nimport _ \"p1/p2/p3/p4\"\n")
1039 tg.tempFile("src/p1/p2/p3/p4/p.go", "package p4\n")
1040 tg.run("list", "-f", "{{.Deps}}", "p1")
1041 tg.grepStdout("p1/p2/p3/p4", "Deps(p1) does not mention p4")
1042
1043 tg.run("list", "-deps", "p1")
1044 tg.grepStdout("p1/p2/p3/p4", "-deps p1 does not mention p4")
1045
1046 if runtime.Compiler != "gccgo" {
1047
1048 tg.run("list", "-deps", "math")
1049 want := "unsafe\ninternal/cpu\nmath/bits\nmath\n"
1050 out := tg.stdout.String()
1051 if !strings.Contains(out, "internal/cpu") {
1052
1053 want = "unsafe\nmath/bits\nmath\n"
1054 }
1055 if tg.stdout.String() != want {
1056 t.Fatalf("list -deps math: wrong order\nhave %q\nwant %q", tg.stdout.String(), want)
1057 }
1058 }
1059 }
1060
1061 func TestGoListCompiledCgo(t *testing.T) {
1062 tooSlow(t, "compiles cgo files")
1063
1064 tg := testgo(t)
1065 defer tg.cleanup()
1066 tg.parallel()
1067 tg.makeTempdir()
1068 tg.setenv("GOCACHE", tg.tempdir)
1069
1070 tg.run("list", "-f", `{{join .CgoFiles "\n"}}`, "net")
1071 if tg.stdout.String() == "" {
1072 t.Skip("net does not use cgo")
1073 }
1074 if strings.Contains(tg.stdout.String(), tg.tempdir) {
1075 t.Fatalf(".CgoFiles unexpectedly mentioned cache %s", tg.tempdir)
1076 }
1077 tg.run("list", "-compiled", "-f", `{{.Dir}}{{"\n"}}{{join .CompiledGoFiles "\n"}}`, "net")
1078 if !strings.Contains(tg.stdout.String(), tg.tempdir) {
1079 t.Fatalf(".CompiledGoFiles with -compiled did not mention cache %s", tg.tempdir)
1080 }
1081 dir := ""
1082 for _, file := range strings.Split(tg.stdout.String(), "\n") {
1083 if file == "" {
1084 continue
1085 }
1086 if dir == "" {
1087 dir = file
1088 continue
1089 }
1090 if !strings.Contains(file, "/") && !strings.Contains(file, `\`) {
1091 file = filepath.Join(dir, file)
1092 }
1093 if _, err := os.Stat(file); err != nil {
1094 t.Fatalf("cannot find .CompiledGoFiles result %s: %v", file, err)
1095 }
1096 }
1097 }
1098
1099 func TestGoListExport(t *testing.T) {
1100 tooSlow(t, "runs build for -export")
1101
1102 skipIfGccgo(t, "gccgo does not have standard packages")
1103 tg := testgo(t)
1104 defer tg.cleanup()
1105 tg.parallel()
1106 tg.makeTempdir()
1107 tg.setenv("GOCACHE", tg.tempdir)
1108
1109 tg.run("list", "-f", "{{.Export}}", "strings")
1110 if tg.stdout.String() != "" {
1111 t.Fatalf(".Export without -export unexpectedly set")
1112 }
1113 tg.run("list", "-export", "-f", "{{.Export}}", "strings")
1114 file := strings.TrimSpace(tg.stdout.String())
1115 if file == "" {
1116 t.Fatalf(".Export with -export was empty")
1117 }
1118 if _, err := os.Stat(file); err != nil {
1119 t.Fatalf("cannot find .Export result %s: %v", file, err)
1120 }
1121
1122 tg.run("list", "-export", "-f", "{{.BuildID}}", "strings")
1123 buildID := strings.TrimSpace(tg.stdout.String())
1124 if buildID == "" {
1125 t.Fatalf(".BuildID with -export was empty")
1126 }
1127
1128 tg.run("tool", "buildid", file)
1129 toolBuildID := strings.TrimSpace(tg.stdout.String())
1130 if buildID != toolBuildID {
1131 t.Fatalf(".BuildID with -export %q disagrees with 'go tool buildid' %q", buildID, toolBuildID)
1132 }
1133 }
1134
1135
1136 func TestUnsuccessfulGoInstallShouldMentionMissingPackage(t *testing.T) {
1137 tg := testgo(t)
1138 defer tg.cleanup()
1139 tg.parallel()
1140 tg.runFail("install", "foo/quxx")
1141 if tg.grepCountBoth(`cannot find package "foo/quxx" in any of`) != 1 {
1142 t.Error(`go install foo/quxx expected error: .*cannot find package "foo/quxx" in any of`)
1143 }
1144 }
1145
1146 func TestGOROOTSearchFailureReporting(t *testing.T) {
1147 tg := testgo(t)
1148 defer tg.cleanup()
1149 tg.parallel()
1150 tg.runFail("install", "foo/quxx")
1151 if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("foo", "quxx"))+` \(from \$GOROOT\)$`) != 1 {
1152 t.Error(`go install foo/quxx expected error: .*foo/quxx (from $GOROOT)`)
1153 }
1154 }
1155
1156 func TestMultipleGOPATHEntriesReportedSeparately(t *testing.T) {
1157 tg := testgo(t)
1158 defer tg.cleanup()
1159 tg.parallel()
1160 sep := string(filepath.ListSeparator)
1161 tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
1162 tg.runFail("install", "foo/quxx")
1163 if tg.grepCountBoth(`testdata[/\\].[/\\]src[/\\]foo[/\\]quxx`) != 2 {
1164 t.Error(`go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)\n.*testdata/b/src/foo/quxx`)
1165 }
1166 }
1167
1168
1169 func TestMentionGOPATHInFirstGOPATHEntry(t *testing.T) {
1170 tg := testgo(t)
1171 defer tg.cleanup()
1172 tg.parallel()
1173 sep := string(filepath.ListSeparator)
1174 tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
1175 tg.runFail("install", "foo/quxx")
1176 if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("testdata", "a", "src", "foo", "quxx"))+` \(from \$GOPATH\)$`) != 1 {
1177 t.Error(`go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)`)
1178 }
1179 }
1180
1181
1182 func TestMentionGOPATHNotOnSecondEntry(t *testing.T) {
1183 tg := testgo(t)
1184 defer tg.cleanup()
1185 tg.parallel()
1186 sep := string(filepath.ListSeparator)
1187 tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
1188 tg.runFail("install", "foo/quxx")
1189 if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("testdata", "b", "src", "foo", "quxx"))+`$`) != 1 {
1190 t.Error(`go install foo/quxx expected error: .*testdata/b/src/foo/quxx`)
1191 }
1192 }
1193
1194 func homeEnvName() string {
1195 switch runtime.GOOS {
1196 case "windows":
1197 return "USERPROFILE"
1198 case "plan9":
1199 return "home"
1200 default:
1201 return "HOME"
1202 }
1203 }
1204
1205 func tempEnvName() string {
1206 switch runtime.GOOS {
1207 case "windows":
1208 return "TMP"
1209 case "plan9":
1210 return "TMPDIR"
1211 default:
1212 return "TMPDIR"
1213 }
1214 }
1215
1216 func pathEnvName() string {
1217 switch runtime.GOOS {
1218 case "plan9":
1219 return "path"
1220 default:
1221 return "PATH"
1222 }
1223 }
1224
1225 func TestDefaultGOPATH(t *testing.T) {
1226 tg := testgo(t)
1227 defer tg.cleanup()
1228 tg.parallel()
1229 tg.tempDir("home/go")
1230 tg.setenv(homeEnvName(), tg.path("home"))
1231
1232
1233
1234 tg.setenv("TEST_TELEMETRY_DIR", "/no-telemetry-dir")
1235
1236 tg.run("env", "GOPATH")
1237 tg.grepStdout(regexp.QuoteMeta(tg.path("home/go")), "want GOPATH=$HOME/go")
1238
1239 tg.setenv("GOROOT", tg.path("home/go"))
1240 tg.run("env", "GOPATH")
1241 tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go")
1242
1243 tg.setenv("GOROOT", tg.path("home/go")+"/")
1244 tg.run("env", "GOPATH")
1245 tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go/")
1246 }
1247
1248 func TestDefaultGOPATHPrintedSearchList(t *testing.T) {
1249 tg := testgo(t)
1250 defer tg.cleanup()
1251 tg.parallel()
1252 tg.setenv("GOPATH", "")
1253 tg.tempDir("home")
1254 tg.setenv(homeEnvName(), tg.path("home"))
1255
1256
1257
1258 tg.setenv("TEST_TELEMETRY_DIR", "/no-telemetry-dir")
1259
1260 tg.runFail("install", "github.com/golang/example/hello")
1261 tg.grepStderr(regexp.QuoteMeta(tg.path("home/go/src/github.com/golang/example/hello"))+`.*from \$GOPATH`, "expected default GOPATH")
1262 }
1263
1264 func TestLdflagsArgumentsWithSpacesIssue3941(t *testing.T) {
1265 skipIfGccgo(t, "gccgo does not support -ldflags -X")
1266 tooSlow(t, "compiles and links a binary")
1267
1268 tg := testgo(t)
1269 defer tg.cleanup()
1270 tg.parallel()
1271 tg.tempFile("main.go", `package main
1272 var extern string
1273 func main() {
1274 println(extern)
1275 }`)
1276 tg.run("run", "-ldflags", `-X "main.extern=hello world"`, tg.path("main.go"))
1277 tg.grepStderr("^hello world", `ldflags -X "main.extern=hello world"' failed`)
1278 }
1279
1280 func TestLdFlagsLongArgumentsIssue42295(t *testing.T) {
1281
1282
1283 skipIfGccgo(t, "gccgo does not support -ldflags -X")
1284 tooSlow(t, "compiles and links a binary")
1285
1286 tg := testgo(t)
1287 defer tg.cleanup()
1288 tg.parallel()
1289 tg.tempFile("main.go", `package main
1290 var extern string
1291 func main() {
1292 print(extern)
1293 }`)
1294 testStr := "test test test test test \n\\ "
1295 var buf strings.Builder
1296 for buf.Len() < sys.ExecArgLengthLimit+1 {
1297 buf.WriteString(testStr)
1298 }
1299 tg.run("run", "-ldflags", fmt.Sprintf(`-X "main.extern=%s"`, buf.String()), tg.path("main.go"))
1300 if tg.stderr.String() != buf.String() {
1301 t.Errorf("strings differ")
1302 }
1303 }
1304
1305 func TestGoTestDashCDashOControlsBinaryLocation(t *testing.T) {
1306 skipIfGccgo(t, "gccgo has no standard packages")
1307 tooSlow(t, "compiles and links a test binary")
1308
1309 tg := testgo(t)
1310 defer tg.cleanup()
1311 tg.parallel()
1312 tg.makeTempdir()
1313 tg.run("test", "-c", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
1314 tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -c -o myerrors.test did not create myerrors.test")
1315 }
1316
1317 func TestGoTestDashOWritesBinary(t *testing.T) {
1318 skipIfGccgo(t, "gccgo has no standard packages")
1319 tooSlow(t, "compiles and runs a test binary")
1320
1321 tg := testgo(t)
1322 defer tg.cleanup()
1323 tg.parallel()
1324 tg.makeTempdir()
1325 tg.run("test", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
1326 tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -o myerrors.test did not create myerrors.test")
1327 }
1328
1329
1330 func TestInstallWithTags(t *testing.T) {
1331 tooSlow(t, "compiles and links binaries")
1332
1333 tg := testgo(t)
1334 defer tg.cleanup()
1335 tg.parallel()
1336 tg.tempDir("bin")
1337 tg.tempFile("src/example/a/main.go", `package main
1338 func main() {}`)
1339 tg.tempFile("src/example/b/main.go", `// +build mytag
1340
1341 package main
1342 func main() {}`)
1343 tg.setenv("GOPATH", tg.path("."))
1344 tg.run("install", "-tags", "mytag", "example/a", "example/b")
1345 tg.wantExecutable(tg.path("bin/a"+exeSuffix), "go install example/a example/b did not install binaries")
1346 tg.wantExecutable(tg.path("bin/b"+exeSuffix), "go install example/a example/b did not install binaries")
1347 tg.must(os.Remove(tg.path("bin/a" + exeSuffix)))
1348 tg.must(os.Remove(tg.path("bin/b" + exeSuffix)))
1349 tg.run("install", "-tags", "mytag", "example/...")
1350 tg.wantExecutable(tg.path("bin/a"+exeSuffix), "go install example/... did not install binaries")
1351 tg.wantExecutable(tg.path("bin/b"+exeSuffix), "go install example/... did not install binaries")
1352 tg.run("list", "-tags", "mytag", "example/b...")
1353 if strings.TrimSpace(tg.getStdout()) != "example/b" {
1354 t.Error("go list example/b did not find example/b")
1355 }
1356 }
1357
1358
1359 func TestSymlinkWarning(t *testing.T) {
1360 tg := testgo(t)
1361 defer tg.cleanup()
1362 tg.parallel()
1363 tg.makeTempdir()
1364 tg.setenv("GOPATH", tg.path("."))
1365
1366 tg.tempDir("src/example/xx")
1367 tg.tempDir("yy/zz")
1368 tg.tempFile("yy/zz/zz.go", "package zz\n")
1369 if err := os.Symlink(tg.path("yy"), tg.path("src/example/xx/yy")); err != nil {
1370 t.Skipf("symlink failed: %v", err)
1371 }
1372 tg.run("list", "example/xx/z...")
1373 tg.grepStdoutNot(".", "list should not have matched anything")
1374 tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages")
1375 tg.grepStderrNot("symlink", "list should not have reported symlink")
1376
1377 tg.run("list", "example/xx/...")
1378 tg.grepStdoutNot(".", "list should not have matched anything")
1379 tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages")
1380 tg.grepStderr("ignoring symlink", "list should have reported symlink")
1381 }
1382
1383 func TestCgoShowsFullPathNames(t *testing.T) {
1384 testenv.MustHaveCGO(t)
1385
1386 tg := testgo(t)
1387 defer tg.cleanup()
1388 tg.parallel()
1389 tg.tempFile("src/x/y/dirname/foo.go", `
1390 package foo
1391 import "C"
1392 func f() {`)
1393 tg.setenv("GOPATH", tg.path("."))
1394 tg.runFail("build", "x/y/dirname")
1395 tg.grepBoth("x/y/dirname", "error did not use full path")
1396 }
1397
1398 func TestCgoHandlesWlORIGIN(t *testing.T) {
1399 tooSlow(t, "compiles cgo files")
1400 testenv.MustHaveCGO(t)
1401
1402 tg := testgo(t)
1403 defer tg.cleanup()
1404 tg.parallel()
1405 tg.tempFile("src/origin/origin.go", `package origin
1406 // #cgo !darwin,!windows LDFLAGS: -Wl,-rpath,$ORIGIN
1407 // void f(void) {}
1408 import "C"
1409 func f() { C.f() }`)
1410 tg.setenv("GOPATH", tg.path("."))
1411 tg.run("build", "origin")
1412 }
1413
1414 func TestCgoPkgConfig(t *testing.T) {
1415 tooSlow(t, "compiles cgo files")
1416 testenv.MustHaveCGO(t)
1417
1418 tg := testgo(t)
1419 defer tg.cleanup()
1420 tg.parallel()
1421
1422 tg.run("env", "PKG_CONFIG")
1423 pkgConfig := strings.TrimSpace(tg.getStdout())
1424 testenv.MustHaveExecPath(t, pkgConfig)
1425 if out, err := testenv.Command(t, pkgConfig, "--atleast-pkgconfig-version", "0.24").CombinedOutput(); err != nil {
1426 t.Skipf("%s --atleast-pkgconfig-version 0.24: %v\n%s", pkgConfig, err, out)
1427 }
1428
1429
1430
1431
1432
1433 tg.tempFile("foo.pc", `
1434 Name: foo
1435 Description: The foo library
1436 Version: 1.0.0
1437 Cflags: -Dhello=10 -Dworld=+32 -DDEFINED_FROM_PKG_CONFIG=hello\ world
1438 `)
1439 tg.tempFile("foo.go", `package main
1440
1441 /*
1442 #cgo pkg-config: foo
1443 int value() {
1444 return DEFINED_FROM_PKG_CONFIG;
1445 }
1446 */
1447 import "C"
1448 import "os"
1449
1450 func main() {
1451 if C.value() != 42 {
1452 println("value() =", C.value(), "wanted 42")
1453 os.Exit(1)
1454 }
1455 }
1456 `)
1457 tg.setenv("PKG_CONFIG_PATH", tg.path("."))
1458 tg.run("run", tg.path("foo.go"))
1459
1460 libs := `Libs: -Wl,-rpath=/path\ with\ spaces/bin`
1461 if runtime.GOOS == "darwin" {
1462 libs = ""
1463 }
1464
1465 tg.tempFile("bar.pc", `
1466 Name: bar
1467 Description: The bar library
1468 Version: 1.0.0
1469 `+libs+`
1470 `)
1471
1472 tg.tempFile("bar.go", `package main
1473 /*
1474 #cgo pkg-config: bar
1475 */
1476 import "C"
1477 func main() {}
1478 `)
1479 tg.run("run", tg.path("bar.go"))
1480 }
1481
1482
1483
1484
1485 func TestImportLocal(t *testing.T) {
1486 tooSlow(t, "builds a lot of sequential packages")
1487
1488 tg := testgo(t)
1489 tg.parallel()
1490 defer tg.cleanup()
1491
1492 tg.tempFile("src/dir/x/x.go", `package x
1493 var X int
1494 `)
1495 tg.setenv("GOPATH", tg.path("."))
1496 tg.run("build", "dir/x")
1497
1498
1499 tg.tempFile("src/dir/p0/p.go", `package p0
1500 import "dir/x"
1501 var _ = x.X
1502 `)
1503 tg.run("build", "dir/p0")
1504
1505
1506 tg.tempFile("src/dir/p1/p.go", `package p1
1507 import "../x"
1508 var _ = x.X
1509 `)
1510 tg.runFail("build", "dir/p1")
1511 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1512
1513
1514 tg.tempFile("src/dir/p2/p.go", `package p2
1515 `)
1516 tg.tempFile("src/dir/p2/p_test.go", `package p2
1517 import "../x"
1518 import "testing"
1519 var _ = x.X
1520 func TestFoo(t *testing.T) {}
1521 `)
1522 tg.run("build", "dir/p2")
1523 tg.runFail("test", "dir/p2")
1524 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1525
1526
1527 tg.tempFile("src/dir/p2/p_test.go", `package p2_test
1528 import "../x"
1529 import "testing"
1530 var _ = x.X
1531 func TestFoo(t *testing.T) {}
1532 `)
1533 tg.run("build", "dir/p2")
1534 tg.runFail("test", "dir/p2")
1535 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1536
1537
1538 tg.tempFile("src/dir/d.go", `package dir
1539 import "./x"
1540 var _ = x.X
1541 `)
1542 tg.runFail("build", "dir")
1543 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1544
1545
1546 tg.tempFile("src/dir/d.go", `package dir
1547 `)
1548 tg.tempFile("src/dir/d_test.go", `package dir
1549 import "./x"
1550 import "testing"
1551 var _ = x.X
1552 func TestFoo(t *testing.T) {}
1553 `)
1554 tg.run("build", "dir")
1555 tg.runFail("test", "dir")
1556 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1557
1558
1559 tg.tempFile("src/dir/d_test.go", `package dir_test
1560 import "./x"
1561 import "testing"
1562 var _ = x.X
1563 func TestFoo(t *testing.T) {}
1564 `)
1565 tg.run("build", "dir")
1566 tg.runFail("test", "dir")
1567 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1568
1569
1570 tg.tempFile("src/dir/x/y/y.go", `package dir
1571 import ".."
1572 var _ = x.X
1573 `)
1574 tg.runFail("build", "dir/x/y")
1575 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1576
1577
1578 tg.tempFile("src/dir/x/y/y.go", `package y
1579 `)
1580 tg.tempFile("src/dir/x/y/y_test.go", `package y
1581 import ".."
1582 import "testing"
1583 var _ = x.X
1584 func TestFoo(t *testing.T) {}
1585 `)
1586 tg.run("build", "dir/x/y")
1587 tg.runFail("test", "dir/x/y")
1588 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1589
1590
1591 tg.tempFile("src/dir/x/y/y_test.go", `package y_test
1592 import ".."
1593 import "testing"
1594 var _ = x.X
1595 func TestFoo(t *testing.T) {}
1596 `)
1597 tg.run("build", "dir/x/y")
1598 tg.runFail("test", "dir/x/y")
1599 tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
1600
1601
1602 tg.tempFile("src/dir/x/xx.go", `package x
1603 import "."
1604 var _ = x.X
1605 `)
1606 tg.runFail("build", "dir/x")
1607 tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
1608
1609
1610 tg.tempFile("src/dir/x/xx.go", `package x
1611 `)
1612 tg.tempFile("src/dir/x/xx_test.go", `package x
1613 import "."
1614 import "testing"
1615 var _ = x.X
1616 func TestFoo(t *testing.T) {}
1617 `)
1618 tg.run("build", "dir/x")
1619 tg.runFail("test", "dir/x")
1620 tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
1621
1622
1623 tg.tempFile("src/dir/x/xx.go", `package x
1624 `)
1625 tg.tempFile("src/dir/x/xx_test.go", `package x_test
1626 import "."
1627 import "testing"
1628 var _ = x.X
1629 func TestFoo(t *testing.T) {}
1630 `)
1631 tg.run("build", "dir/x")
1632 tg.runFail("test", "dir/x")
1633 tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
1634 }
1635
1636 func TestGoInstallPkgdir(t *testing.T) {
1637 skipIfGccgo(t, "gccgo has no standard packages")
1638 tooSlow(t, "builds a package with cgo dependencies")
1639
1640
1641
1642 testenv.MustHaveCGO(t)
1643
1644 tg := testgo(t)
1645 tg.parallel()
1646 tg.setenv("GODEBUG", "installgoroot=all")
1647 defer tg.cleanup()
1648 tg.makeTempdir()
1649 pkg := tg.path(".")
1650 tg.run("install", "-pkgdir", pkg, "net")
1651 tg.mustExist(filepath.Join(pkg, "net.a"))
1652 tg.mustNotExist(filepath.Join(pkg, "runtime/cgo.a"))
1653 }
1654
1655
1656 func TestParallelTest(t *testing.T) {
1657 tooSlow(t, "links and runs test binaries")
1658
1659 tg := testgo(t)
1660 tg.parallel()
1661 defer tg.cleanup()
1662 tg.makeTempdir()
1663 const testSrc = `package package_test
1664 import (
1665 "testing"
1666 )
1667 func TestTest(t *testing.T) {
1668 }`
1669 tg.tempFile("src/p1/p1_test.go", strings.Replace(testSrc, "package_test", "p1_test", 1))
1670 tg.tempFile("src/p2/p2_test.go", strings.Replace(testSrc, "package_test", "p2_test", 1))
1671 tg.tempFile("src/p3/p3_test.go", strings.Replace(testSrc, "package_test", "p3_test", 1))
1672 tg.tempFile("src/p4/p4_test.go", strings.Replace(testSrc, "package_test", "p4_test", 1))
1673 tg.setenv("GOPATH", tg.path("."))
1674 tg.run("test", "-p=4", "p1", "p2", "p3", "p4")
1675 }
1676
1677
1678 func TestLinkSysoFiles(t *testing.T) {
1679 if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
1680 t.Skip("not linux/amd64")
1681 }
1682
1683 tg := testgo(t)
1684 defer tg.cleanup()
1685 tg.parallel()
1686 tg.tempDir("src/syso")
1687 tg.tempFile("src/syso/a.syso", ``)
1688 tg.tempFile("src/syso/b.go", `package syso`)
1689 tg.setenv("GOPATH", tg.path("."))
1690
1691
1692
1693
1694 tg.setenv("CGO_ENABLED", "1")
1695 tg.run("list", "-f", "{{.SysoFiles}}", "syso")
1696 tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=1")
1697
1698 tg.setenv("CGO_ENABLED", "0")
1699 tg.run("list", "-f", "{{.SysoFiles}}", "syso")
1700 tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=0")
1701
1702 tg.setenv("CGO_ENABLED", "1")
1703 tg.run("list", "-msan", "-f", "{{.SysoFiles}}", "syso")
1704 tg.grepStdoutNot("a.syso", "unexpected syso file with -msan")
1705 }
1706
1707
1708 func TestGenerateUsesBuildContext(t *testing.T) {
1709 if runtime.GOOS == "windows" {
1710 t.Skip("this test won't run under Windows")
1711 }
1712
1713 tg := testgo(t)
1714 defer tg.cleanup()
1715 tg.parallel()
1716 tg.tempDir("src/gen")
1717 tg.tempFile("src/gen/gen.go", "package gen\n//go:generate echo $GOOS $GOARCH\n")
1718 tg.setenv("GOPATH", tg.path("."))
1719
1720 tg.setenv("GOOS", "linux")
1721 tg.setenv("GOARCH", "amd64")
1722 tg.run("generate", "gen")
1723 tg.grepStdout("linux amd64", "unexpected GOOS/GOARCH combination")
1724
1725 tg.setenv("GOOS", "darwin")
1726 tg.setenv("GOARCH", "arm64")
1727 tg.run("generate", "gen")
1728 tg.grepStdout("darwin arm64", "unexpected GOOS/GOARCH combination")
1729 }
1730
1731 func TestGoEnv(t *testing.T) {
1732 tg := testgo(t)
1733 tg.parallel()
1734 defer tg.cleanup()
1735 tg.setenv("GOOS", "freebsd")
1736 tg.setenv("GOARCH", "arm")
1737 tg.run("env", "GOARCH")
1738 tg.grepStdout("^arm$", "GOARCH not honored")
1739
1740 tg.run("env", "GCCGO")
1741 tg.grepStdout(".", "GCCGO unexpectedly empty")
1742
1743 tg.run("env", "CGO_CFLAGS")
1744 tg.grepStdout(".", "default CGO_CFLAGS unexpectedly empty")
1745
1746 tg.setenv("CGO_CFLAGS", "-foobar")
1747 tg.run("env", "CGO_CFLAGS")
1748 tg.grepStdout("^-foobar$", "CGO_CFLAGS not honored")
1749
1750 tg.setenv("CC", "gcc -fmust -fgo -ffaster")
1751 tg.run("env", "CC")
1752 tg.grepStdout("gcc", "CC not found")
1753 tg.run("env", "GOGCCFLAGS")
1754 tg.grepStdout("-ffaster", "CC arguments not found")
1755
1756 tg.run("env", "GOVERSION")
1757 envVersion := strings.TrimSpace(tg.stdout.String())
1758
1759 tg.run("version")
1760 cmdVersion := strings.TrimSpace(tg.stdout.String())
1761
1762
1763
1764 if cmdVersion == envVersion || !strings.Contains(cmdVersion, envVersion) {
1765 t.Fatalf("'go env GOVERSION' %q should be a shorter substring of 'go version' %q", envVersion, cmdVersion)
1766 }
1767 }
1768
1769 const (
1770 noMatchesPattern = `(?m)^ok.*\[no tests to run\]`
1771 okPattern = `(?m)^ok`
1772 )
1773
1774
1775 func TestLdBindNow(t *testing.T) {
1776 tg := testgo(t)
1777 defer tg.cleanup()
1778 tg.parallel()
1779 tg.setenv("LD_BIND_NOW", "1")
1780 tg.run("help")
1781 }
1782
1783
1784
1785 func TestConcurrentAsm(t *testing.T) {
1786 skipIfGccgo(t, "gccgo does not use cmd/asm")
1787 tg := testgo(t)
1788 defer tg.cleanup()
1789 tg.parallel()
1790 asm := `DATA ·constants<>+0x0(SB)/8,$0
1791 GLOBL ·constants<>(SB),8,$8
1792 `
1793 tg.tempFile("go/src/p/a.s", asm)
1794 tg.tempFile("go/src/p/b.s", asm)
1795 tg.tempFile("go/src/p/p.go", `package p`)
1796 tg.setenv("GOPATH", tg.path("go"))
1797 tg.run("build", "p")
1798 }
1799
1800
1801 func TestFFLAGS(t *testing.T) {
1802 testenv.MustHaveCGO(t)
1803
1804 tg := testgo(t)
1805 defer tg.cleanup()
1806 tg.parallel()
1807
1808 tg.tempFile("p/src/p/main.go", `package main
1809 // #cgo FFLAGS: -no-such-fortran-flag
1810 import "C"
1811 func main() {}
1812 `)
1813 tg.tempFile("p/src/p/a.f", `! comment`)
1814 tg.setenv("GOPATH", tg.path("p"))
1815
1816
1817
1818
1819 tg.doRun([]string{"build", "-x", "p"})
1820
1821 tg.grepStderr("no-such-fortran-flag", `missing expected "-no-such-fortran-flag"`)
1822 }
1823
1824
1825
1826 func TestDuplicateGlobalAsmSymbols(t *testing.T) {
1827 skipIfGccgo(t, "gccgo does not use cmd/asm")
1828 tooSlow(t, "links a binary with cgo dependencies")
1829 if runtime.GOARCH != "386" && runtime.GOARCH != "amd64" {
1830 t.Skipf("skipping test on %s", runtime.GOARCH)
1831 }
1832 testenv.MustHaveCGO(t)
1833
1834 tg := testgo(t)
1835 defer tg.cleanup()
1836 tg.parallel()
1837
1838 asm := `
1839 #include "textflag.h"
1840
1841 DATA sym<>+0x0(SB)/8,$0
1842 GLOBL sym<>(SB),(NOPTR+RODATA),$8
1843
1844 TEXT ·Data(SB),NOSPLIT,$0
1845 MOVB sym<>(SB), AX
1846 MOVB AX, ret+0(FP)
1847 RET
1848 `
1849 tg.tempFile("go/src/a/a.s", asm)
1850 tg.tempFile("go/src/a/a.go", `package a; func Data() uint8`)
1851 tg.tempFile("go/src/b/b.s", asm)
1852 tg.tempFile("go/src/b/b.go", `package b; func Data() uint8`)
1853 tg.tempFile("go/src/p/p.go", `
1854 package main
1855 import "a"
1856 import "b"
1857 import "C"
1858 func main() {
1859 _ = a.Data() + b.Data()
1860 }
1861 `)
1862 tg.setenv("GOPATH", tg.path("go"))
1863 exe := tg.path("p.exe")
1864 tg.creatingTemp(exe)
1865 tg.run("build", "-o", exe, "p")
1866 }
1867
1868 func copyFile(src, dst string, perm fs.FileMode) error {
1869 sf, err := os.Open(src)
1870 if err != nil {
1871 return err
1872 }
1873 defer sf.Close()
1874
1875 df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
1876 if err != nil {
1877 return err
1878 }
1879
1880 _, err = io.Copy(df, sf)
1881 err2 := df.Close()
1882 if err != nil {
1883 return err
1884 }
1885 return err2
1886 }
1887
1888 func TestNeedVersion(t *testing.T) {
1889 skipIfGccgo(t, "gccgo does not use cmd/compile")
1890 tg := testgo(t)
1891 defer tg.cleanup()
1892 tg.parallel()
1893 tg.tempFile("goversion.go", `package main; func main() {}`)
1894 path := tg.path("goversion.go")
1895 tg.setenv("TESTGO_TOOLCHAIN_VERSION", "go1.testgo")
1896 tg.runFail("run", path)
1897 tg.grepStderr("compile", "does not match go tool version")
1898 }
1899
1900 func TestBuildmodePIE(t *testing.T) {
1901 tooSlow(t, "links binaries")
1902 t.Parallel()
1903
1904 if !platform.BuildModeSupported(runtime.Compiler, "pie", runtime.GOOS, runtime.GOARCH) {
1905 t.Skipf("skipping test because buildmode=pie is not supported on %s/%s", runtime.GOOS, runtime.GOARCH)
1906 }
1907
1908 if strings.HasSuffix(testenv.Builder(), "-alpine") {
1909 t.Skip("skipping PIE tests on alpine; see https://go.dev/issues/54354")
1910 }
1911 t.Run("non-cgo", func(t *testing.T) {
1912 testBuildmodePIE(t, false, true)
1913 })
1914 t.Run("cgo", func(t *testing.T) {
1915 testenv.MustHaveCGO(t)
1916 testBuildmodePIE(t, true, true)
1917 })
1918 }
1919
1920 func TestWindowsDefaultBuildmodIsPIE(t *testing.T) {
1921 if runtime.GOOS != "windows" {
1922 t.Skip("skipping windows only test")
1923 }
1924 tooSlow(t, "links binaries")
1925 t.Parallel()
1926
1927 t.Run("non-cgo", func(t *testing.T) {
1928 testBuildmodePIE(t, false, false)
1929 })
1930 t.Run("cgo", func(t *testing.T) {
1931 testenv.MustHaveCGO(t)
1932 testBuildmodePIE(t, true, false)
1933 })
1934 }
1935
1936 func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) {
1937 tg := testgo(t)
1938 defer tg.cleanup()
1939 tg.parallel()
1940
1941 var s string
1942 if useCgo {
1943 s = `import "C";`
1944 }
1945 tg.tempFile("main.go", fmt.Sprintf(`package main;%s func main() { print("hello") }`, s))
1946 src := tg.path("main.go")
1947 obj := tg.path("main.exe")
1948 args := []string{"build"}
1949 if setBuildmodeToPIE {
1950 args = append(args, "-buildmode=pie")
1951 }
1952 args = append(args, "-o", obj, src)
1953 tg.run(args...)
1954
1955 switch runtime.GOOS {
1956 case "linux", "android", "freebsd":
1957 f, err := elf.Open(obj)
1958 if err != nil {
1959 t.Fatal(err)
1960 }
1961 defer f.Close()
1962 if f.Type != elf.ET_DYN {
1963 t.Errorf("PIE type must be ET_DYN, but %s", f.Type)
1964 }
1965 case "darwin", "ios":
1966 f, err := macho.Open(obj)
1967 if err != nil {
1968 t.Fatal(err)
1969 }
1970 defer f.Close()
1971 if f.Flags&macho.FlagDyldLink == 0 {
1972 t.Error("PIE must have DyldLink flag, but not")
1973 }
1974 if f.Flags&macho.FlagPIE == 0 {
1975 t.Error("PIE must have PIE flag, but not")
1976 }
1977 case "windows":
1978 f, err := pe.Open(obj)
1979 if err != nil {
1980 t.Fatal(err)
1981 }
1982 defer f.Close()
1983 if f.Section(".reloc") == nil {
1984 t.Error(".reloc section is not present")
1985 }
1986 if (f.FileHeader.Characteristics & pe.IMAGE_FILE_RELOCS_STRIPPED) != 0 {
1987 t.Error("IMAGE_FILE_RELOCS_STRIPPED flag is set")
1988 }
1989 var dc uint16
1990 switch oh := f.OptionalHeader.(type) {
1991 case *pe.OptionalHeader32:
1992 dc = oh.DllCharacteristics
1993 case *pe.OptionalHeader64:
1994 dc = oh.DllCharacteristics
1995 if (dc & pe.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) == 0 {
1996 t.Error("IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA flag is not set")
1997 }
1998 default:
1999 t.Fatalf("unexpected optional header type of %T", f.OptionalHeader)
2000 }
2001 if (dc & pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 {
2002 t.Error("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag is not set")
2003 }
2004 default:
2005
2006
2007 t.Skipf("skipping test: test helper does not support %s", runtime.GOOS)
2008 }
2009
2010 out, err := testenv.Command(t, obj).CombinedOutput()
2011 if err != nil {
2012 t.Fatal(err)
2013 }
2014
2015 if string(out) != "hello" {
2016 t.Errorf("got %q; want %q", out, "hello")
2017 }
2018 }
2019
2020 func TestUpxCompression(t *testing.T) {
2021 if runtime.GOOS != "linux" ||
2022 (runtime.GOARCH != "amd64" && runtime.GOARCH != "386") {
2023 t.Skipf("skipping upx test on %s/%s", runtime.GOOS, runtime.GOARCH)
2024 }
2025
2026 testenv.MustHaveExecPath(t, "upx")
2027 out, err := testenv.Command(t, "upx", "--version").CombinedOutput()
2028 if err != nil {
2029 t.Fatalf("upx --version failed: %v", err)
2030 }
2031
2032
2033
2034
2035 re := regexp.MustCompile(`([[:digit:]]+)\.([[:digit:]]+)`)
2036 upxVersion := re.FindStringSubmatch(string(out))
2037 if len(upxVersion) != 3 {
2038 t.Fatalf("bad upx version string: %s", upxVersion)
2039 }
2040
2041 major, err1 := strconv.Atoi(upxVersion[1])
2042 minor, err2 := strconv.Atoi(upxVersion[2])
2043 if err1 != nil || err2 != nil {
2044 t.Fatalf("bad upx version string: %s", upxVersion[0])
2045 }
2046
2047
2048 if (major < 3) || (major == 3 && minor < 94) {
2049 t.Skipf("skipping because upx version %v.%v is too old", major, minor)
2050 }
2051
2052 tg := testgo(t)
2053 defer tg.cleanup()
2054 tg.parallel()
2055
2056 tg.tempFile("main.go", `package main; import "fmt"; func main() { fmt.Print("hello upx") }`)
2057 src := tg.path("main.go")
2058 obj := tg.path("main")
2059 tg.run("build", "-o", obj, src)
2060
2061 out, err = testenv.Command(t, "upx", obj).CombinedOutput()
2062 if err != nil {
2063 t.Logf("executing upx\n%s\n", out)
2064 t.Fatalf("upx failed with %v", err)
2065 }
2066
2067 out, err = testenv.Command(t, obj).CombinedOutput()
2068 if err != nil {
2069 t.Logf("%s", out)
2070 t.Fatalf("running compressed go binary failed with error %s", err)
2071 }
2072 if string(out) != "hello upx" {
2073 t.Fatalf("bad output from compressed go binary:\ngot %q; want %q", out, "hello upx")
2074 }
2075 }
2076
2077 var gocacheverify = godebug.New("#gocacheverify")
2078
2079 func TestCacheListStale(t *testing.T) {
2080 tooSlow(t, "links a binary")
2081 if gocacheverify.Value() == "1" {
2082 t.Skip("GODEBUG gocacheverify")
2083 }
2084
2085 tg := testgo(t)
2086 defer tg.cleanup()
2087 tg.parallel()
2088 tg.makeTempdir()
2089 tg.setenv("GOCACHE", tg.path("cache"))
2090 tg.tempFile("gopath/src/p/p.go", "package p; import _ \"q\"; func F(){}\n")
2091 tg.tempFile("gopath/src/q/q.go", "package q; func F(){}\n")
2092 tg.tempFile("gopath/src/m/m.go", "package main; import _ \"q\"; func main(){}\n")
2093
2094 tg.setenv("GOPATH", tg.path("gopath"))
2095 tg.run("install", "p", "m")
2096 tg.run("list", "-f={{.ImportPath}} {{.Stale}}", "m", "q", "p")
2097 tg.grepStdout("^m false", "m should not be stale")
2098 tg.grepStdout("^q true", "q should be stale")
2099 tg.grepStdout("^p false", "p should not be stale")
2100 }
2101
2102 func TestCacheCoverage(t *testing.T) {
2103 tooSlow(t, "links and runs a test binary with coverage enabled")
2104 if gocacheverify.Value() == "1" {
2105 t.Skip("GODEBUG gocacheverify")
2106 }
2107
2108 tg := testgo(t)
2109 defer tg.cleanup()
2110 tg.parallel()
2111 tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
2112 tg.makeTempdir()
2113
2114 tg.setenv("GOCACHE", tg.path("c1"))
2115 tg.run("test", "-cover", "-short", "strings")
2116 tg.run("test", "-cover", "-short", "math", "strings")
2117 }
2118
2119 func TestIssue22531(t *testing.T) {
2120 tooSlow(t, "links binaries")
2121 if gocacheverify.Value() == "1" {
2122 t.Skip("GODEBUG gocacheverify")
2123 }
2124
2125 tg := testgo(t)
2126 defer tg.cleanup()
2127 tg.parallel()
2128 tg.makeTempdir()
2129 tg.setenv("GOPATH", tg.tempdir)
2130 tg.setenv("GOCACHE", tg.path("cache"))
2131 tg.tempFile("src/m/main.go", "package main /* c1 */; func main() {}\n")
2132 tg.run("install", "-x", "m")
2133 tg.run("list", "-f", "{{.Stale}}", "m")
2134 tg.grepStdout("false", "reported m as stale after install")
2135 tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix))
2136
2137
2138
2139
2140
2141
2142 tg.tempFile("src/m/main.go", "package main /* c2 */; func main() {}\n")
2143 tg.run("install", "-x", "m")
2144 tg.run("list", "-f", "{{.Stale}}", "m")
2145 tg.grepStdout("false", "reported m as stale after reinstall")
2146 tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix))
2147 }
2148
2149 func TestIssue22596(t *testing.T) {
2150 tooSlow(t, "links binaries")
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.makeTempdir()
2159 tg.setenv("GOCACHE", tg.path("cache"))
2160 tg.tempFile("gopath1/src/p/p.go", "package p; func F(){}\n")
2161 tg.tempFile("gopath2/src/p/p.go", "package p; func F(){}\n")
2162
2163 tg.setenv("GOPATH", tg.path("gopath1"))
2164 tg.run("list", "-f={{.Target}}", "p")
2165 target1 := strings.TrimSpace(tg.getStdout())
2166 tg.run("install", "p")
2167 tg.wantNotStale("p", "", "p stale after install")
2168
2169 tg.setenv("GOPATH", tg.path("gopath2"))
2170 tg.run("list", "-f={{.Target}}", "p")
2171 target2 := strings.TrimSpace(tg.getStdout())
2172 tg.must(os.MkdirAll(filepath.Dir(target2), 0777))
2173 tg.must(copyFile(target1, target2, 0666))
2174 tg.wantStale("p", "build ID mismatch", "p not stale after copy from gopath1")
2175 tg.run("install", "p")
2176 tg.wantNotStale("p", "", "p stale after install2")
2177 }
2178
2179 func TestTestCache(t *testing.T) {
2180 tooSlow(t, "links and runs test binaries")
2181 if gocacheverify.Value() == "1" {
2182 t.Skip("GODEBUG gocacheverify")
2183 }
2184
2185 tg := testgo(t)
2186 defer tg.cleanup()
2187 tg.parallel()
2188 tg.makeTempdir()
2189 tg.setenv("GOPATH", tg.tempdir)
2190 tg.setenv("GOCACHE", tg.path("cache"))
2191
2192
2193
2194 t.Log("\n\nINITIAL\n\n")
2195
2196 tg.tempFile("src/p1/p1.go", "package p1\nvar X = 1\n")
2197 tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\nvar X = 1\n")
2198 tg.tempFile("src/t/t1/t1_test.go", "package t\nimport \"testing\"\nfunc Test1(*testing.T) {}\n")
2199 tg.tempFile("src/t/t2/t2_test.go", "package t\nimport _ \"p1\"\nimport \"testing\"\nfunc Test2(*testing.T) {}\n")
2200 tg.tempFile("src/t/t3/t3_test.go", "package t\nimport \"p1\"\nimport \"testing\"\nfunc Test3(t *testing.T) {t.Log(p1.X)}\n")
2201 tg.tempFile("src/t/t4/t4_test.go", "package t\nimport \"p2\"\nimport \"testing\"\nfunc Test4(t *testing.T) {t.Log(p2.X)}")
2202 tg.run("test", "-x", "-v", "-short", "t/...")
2203
2204 t.Log("\n\nREPEAT\n\n")
2205
2206 tg.run("test", "-x", "-v", "-short", "t/...")
2207 tg.grepStdout(`ok \tt/t1\t\(cached\)`, "did not cache t1")
2208 tg.grepStdout(`ok \tt/t2\t\(cached\)`, "did not cache t2")
2209 tg.grepStdout(`ok \tt/t3\t\(cached\)`, "did not cache t3")
2210 tg.grepStdout(`ok \tt/t4\t\(cached\)`, "did not cache t4")
2211 tg.grepStderrNot(`[\\/](compile|gccgo) `, "incorrectly ran compiler")
2212 tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker")
2213 tg.grepStderrNot(`p[0-9]\.test`, "incorrectly ran test")
2214
2215 t.Log("\n\nCOMMENT\n\n")
2216
2217
2218
2219 tg.tempFile("src/p1/p1.go", "package p1\nvar X = 01\n")
2220 tg.run("test", "-p=1", "-x", "-v", "-short", "t/...")
2221 tg.grepStdout(`ok \tt/t1\t\(cached\)`, "did not cache t1")
2222 tg.grepStdout(`ok \tt/t2\t\(cached\)`, "did not cache t2")
2223 tg.grepStdout(`ok \tt/t3\t\(cached\)`, "did not cache t3")
2224 tg.grepStdout(`ok \tt/t4\t\(cached\)`, "did not cache t4")
2225 tg.grepStderrNot(`([\\/](compile|gccgo) ).*t[0-9]_test\.go`, "incorrectly ran compiler")
2226 tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker")
2227 tg.grepStderrNot(`t[0-9]\.test.*test\.short`, "incorrectly ran test")
2228
2229 t.Log("\n\nCHANGE\n\n")
2230
2231
2232 tg.tempFile("src/p1/p1.go", "package p1\nvar X = 02\n")
2233 tg.run("test", "-p=1", "-x", "-v", "-short", "t/...")
2234
2235
2236 tg.grepStderr(`([\\/]compile|gccgo).*p2.go`, "did not recompile p2")
2237
2238
2239 tg.grepStderrNot(`([\\/]compile|gccgo).*t1_test.go`, "incorrectly recompiled t1")
2240 tg.grepStderrNot(`([\\/]link|gccgo).*t1_test`, "incorrectly relinked t1_test")
2241 tg.grepStdout(`ok \tt/t1\t\(cached\)`, "did not cache t/t1")
2242
2243
2244
2245
2246 tg.grepStderr(`([\\/]compile|gccgo).*t2_test.go`, "did not recompile t2")
2247 tg.grepStderr(`([\\/]link|gccgo).*t2\.test`, "did not relink t2_test")
2248
2249
2250 if runtime.Compiler != "gccgo" {
2251 tg.grepStdout(`ok \tt/t2\t\(cached\)`, "did not cache t/t2")
2252 }
2253
2254
2255 tg.grepStderr(`([\\/]compile|gccgo).*t3_test.go`, "did not recompile t3")
2256 tg.grepStderr(`([\\/]link|gccgo).*t3\.test`, "did not relink t3_test")
2257 tg.grepStderr(`t3\.test.*-test.short`, "did not rerun t3_test")
2258 tg.grepStdoutNot(`ok \tt/t3\t\(cached\)`, "reported cached t3_test result")
2259
2260
2261
2262 tg.grepStderrNot(`([\\/]compile|gccgo).*t4_test.go`, "incorrectly recompiled t4")
2263 tg.grepStderr(`([\\/]link|gccgo).*t4\.test`, "did not relink t4_test")
2264
2265
2266 if runtime.Compiler != "gccgo" {
2267 tg.grepStdout(`ok \tt/t4\t\(cached\)`, "did not cache t/t4")
2268 }
2269 }
2270
2271 func TestTestSkipVetAfterFailedBuild(t *testing.T) {
2272 tg := testgo(t)
2273 defer tg.cleanup()
2274 tg.parallel()
2275
2276 tg.tempFile("x_test.go", `package x
2277 func f() {
2278 return 1
2279 }
2280 `)
2281
2282 tg.runFail("test", tg.path("x_test.go"))
2283 tg.grepStderrNot(`vet`, "vet should be skipped after the failed build")
2284 }
2285
2286 func TestTestVetRebuild(t *testing.T) {
2287 tooSlow(t, "links and runs test binaries")
2288
2289 tg := testgo(t)
2290 defer tg.cleanup()
2291 tg.parallel()
2292
2293
2294
2295
2296
2297 tg.tempFile("src/a/a.go", `package a
2298 import "b"
2299 type Type struct{}
2300 func (*Type) M() b.T {return 0}
2301 `)
2302 tg.tempFile("src/b/b.go", `package b
2303 type T int
2304 type I interface {M() T}
2305 `)
2306 tg.tempFile("src/b/export_test.go", `package b
2307 func (*T) Method() *T { return nil }
2308 `)
2309 tg.tempFile("src/b/b_test.go", `package b_test
2310 import (
2311 "testing"
2312 "a"
2313 . "b"
2314 )
2315 func TestBroken(t *testing.T) {
2316 x := new(T)
2317 x.Method()
2318 _ = new(a.Type)
2319 }
2320 `)
2321
2322 tg.setenv("GOPATH", tg.path("."))
2323 tg.run("test", "b")
2324 tg.run("vet", "b")
2325 }
2326
2327 func TestInstallDeps(t *testing.T) {
2328 tooSlow(t, "links a binary")
2329
2330 tg := testgo(t)
2331 defer tg.cleanup()
2332 tg.parallel()
2333 tg.makeTempdir()
2334 tg.setenv("GOPATH", tg.tempdir)
2335
2336 tg.tempFile("src/p1/p1.go", "package p1\nvar X = 1\n")
2337 tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\n")
2338 tg.tempFile("src/main1/main.go", "package main\nimport _ \"p2\"\nfunc main() {}\n")
2339
2340 tg.run("list", "-f={{.Target}}", "p1")
2341 p1 := strings.TrimSpace(tg.getStdout())
2342 tg.run("list", "-f={{.Target}}", "p2")
2343 p2 := strings.TrimSpace(tg.getStdout())
2344 tg.run("list", "-f={{.Target}}", "main1")
2345 main1 := strings.TrimSpace(tg.getStdout())
2346
2347 tg.run("install", "main1")
2348
2349 tg.mustExist(main1)
2350 tg.mustNotExist(p2)
2351 tg.mustNotExist(p1)
2352
2353 tg.run("install", "p2")
2354 tg.mustExist(p2)
2355 tg.mustNotExist(p1)
2356 }
2357
2358
2359 func TestImportPath(t *testing.T) {
2360 tooSlow(t, "links and runs a test binary")
2361
2362 tg := testgo(t)
2363 defer tg.cleanup()
2364 tg.parallel()
2365
2366 tg.tempFile("src/a/a.go", `
2367 package main
2368
2369 import (
2370 "log"
2371 p "a/p-1.0"
2372 )
2373
2374 func main() {
2375 if !p.V {
2376 log.Fatal("false")
2377 }
2378 }`)
2379
2380 tg.tempFile("src/a/a_test.go", `
2381 package main_test
2382
2383 import (
2384 p "a/p-1.0"
2385 "testing"
2386 )
2387
2388 func TestV(t *testing.T) {
2389 if !p.V {
2390 t.Fatal("false")
2391 }
2392 }`)
2393
2394 tg.tempFile("src/a/p-1.0/p.go", `
2395 package p
2396
2397 var V = true
2398
2399 func init() {}
2400 `)
2401
2402 tg.setenv("GOPATH", tg.path("."))
2403 tg.run("build", "-o", tg.path("a.exe"), "a")
2404 tg.run("test", "a")
2405 }
2406
2407 func TestBadCommandLines(t *testing.T) {
2408 tg := testgo(t)
2409 defer tg.cleanup()
2410 tg.parallel()
2411
2412 tg.tempFile("src/x/x.go", "package x\n")
2413 tg.setenv("GOPATH", tg.path("."))
2414
2415 tg.run("build", "x")
2416
2417 tg.tempFile("src/x/@y.go", "package x\n")
2418 tg.runFail("build", "x")
2419 tg.grepStderr("invalid input file name \"@y.go\"", "did not reject @y.go")
2420 tg.must(os.Remove(tg.path("src/x/@y.go")))
2421
2422 tg.tempFile("src/x/-y.go", "package x\n")
2423 tg.runFail("build", "x")
2424 tg.grepStderr("invalid input file name \"-y.go\"", "did not reject -y.go")
2425 tg.must(os.Remove(tg.path("src/x/-y.go")))
2426
2427 if runtime.Compiler == "gccgo" {
2428 tg.runFail("build", "-gccgoflags=all=@x", "x")
2429 } else {
2430 tg.runFail("build", "-gcflags=all=@x", "x")
2431 }
2432 tg.grepStderr("invalid command-line argument @x in command", "did not reject @x during exec")
2433
2434 tg.tempFile("src/@x/x.go", "package x\n")
2435 tg.setenv("GOPATH", tg.path("."))
2436 tg.runFail("build", "@x")
2437 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")
2438
2439 tg.tempFile("src/@x/y/y.go", "package y\n")
2440 tg.setenv("GOPATH", tg.path("."))
2441 tg.runFail("build", "@x/y")
2442 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")
2443
2444 tg.tempFile("src/-x/x.go", "package x\n")
2445 tg.setenv("GOPATH", tg.path("."))
2446 tg.runFail("build", "--", "-x")
2447 tg.grepStderr("invalid import path \"-x\"", "did not reject -x import path")
2448
2449 tg.tempFile("src/-x/y/y.go", "package y\n")
2450 tg.setenv("GOPATH", tg.path("."))
2451 tg.runFail("build", "--", "-x/y")
2452 tg.grepStderr("invalid import path \"-x/y\"", "did not reject -x/y import path")
2453 }
2454
2455 func TestTwoPkgConfigs(t *testing.T) {
2456 testenv.MustHaveCGO(t)
2457 if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
2458 t.Skipf("no shell scripts on %s", runtime.GOOS)
2459 }
2460 tooSlow(t, "builds a package with cgo dependencies")
2461
2462 tg := testgo(t)
2463 defer tg.cleanup()
2464 tg.parallel()
2465 tg.tempFile("src/x/a.go", `package x
2466 // #cgo pkg-config: --static a
2467 import "C"
2468 `)
2469 tg.tempFile("src/x/b.go", `package x
2470 // #cgo pkg-config: --static a
2471 import "C"
2472 `)
2473 tg.tempFile("pkg-config.sh", `#!/bin/sh
2474 echo $* >>`+tg.path("pkg-config.out"))
2475 tg.must(os.Chmod(tg.path("pkg-config.sh"), 0755))
2476 tg.setenv("GOPATH", tg.path("."))
2477 tg.setenv("PKG_CONFIG", tg.path("pkg-config.sh"))
2478 tg.run("build", "x")
2479 out, err := os.ReadFile(tg.path("pkg-config.out"))
2480 tg.must(err)
2481 out = bytes.TrimSpace(out)
2482 want := "--cflags --static --static -- a a\n--libs --static --static -- a a"
2483 if !bytes.Equal(out, []byte(want)) {
2484 t.Errorf("got %q want %q", out, want)
2485 }
2486 }
2487
2488 func TestCgoCache(t *testing.T) {
2489 testenv.MustHaveCGO(t)
2490 tooSlow(t, "builds a package with cgo dependencies")
2491
2492 tg := testgo(t)
2493 defer tg.cleanup()
2494 tg.parallel()
2495 tg.tempFile("src/x/a.go", `package main
2496 // #ifndef VAL
2497 // #define VAL 0
2498 // #endif
2499 // int val = VAL;
2500 import "C"
2501 import "fmt"
2502 func main() { fmt.Println(C.val) }
2503 `)
2504 tg.setenv("GOPATH", tg.path("."))
2505 exe := tg.path("x.exe")
2506 tg.run("build", "-o", exe, "x")
2507 tg.setenv("CGO_LDFLAGS", "-lnosuchlibraryexists")
2508 tg.runFail("build", "-o", exe, "x")
2509 tg.grepStderr(`nosuchlibraryexists`, "did not run linker with changed CGO_LDFLAGS")
2510 }
2511
2512
2513 func TestFilepathUnderCwdFormat(t *testing.T) {
2514 tg := testgo(t)
2515 defer tg.cleanup()
2516 tg.parallel()
2517 tg.run("test", "-x", "-cover", "log")
2518 tg.grepStderrNot(`\.log\.cover\.go`, "-x output should contain correctly formatted filepath under cwd")
2519 }
2520
2521
2522 func TestDontReportRemoveOfEmptyDir(t *testing.T) {
2523 tg := testgo(t)
2524 defer tg.cleanup()
2525 tg.parallel()
2526 tg.tempFile("src/a/a.go", `package a`)
2527 tg.setenv("GOPATH", tg.path("."))
2528 tg.run("install", "-x", "a")
2529 tg.run("install", "-x", "a")
2530
2531
2532 if bytes.Count(tg.stdout.Bytes(), []byte{'\n'})+bytes.Count(tg.stderr.Bytes(), []byte{'\n'}) > 1 {
2533 t.Error("unnecessary output when installing installed package")
2534 }
2535 }
2536
2537
2538 func TestLinkerTmpDirIsDeleted(t *testing.T) {
2539 skipIfGccgo(t, "gccgo does not use cmd/link")
2540 testenv.MustHaveCGO(t)
2541 tooSlow(t, "builds a package with cgo dependencies")
2542
2543 tg := testgo(t)
2544 defer tg.cleanup()
2545 tg.parallel()
2546 tg.tempFile("a.go", `package main; import "C"; func main() {}`)
2547 tg.run("build", "-ldflags", "-v", "-o", os.DevNull, tg.path("a.go"))
2548
2549 stderr := tg.getStderr()
2550 var hostLinkLine string
2551 for _, line := range strings.Split(stderr, "\n") {
2552 if !strings.Contains(line, "host link:") {
2553 continue
2554 }
2555 hostLinkLine = line
2556 break
2557 }
2558 if hostLinkLine == "" {
2559 t.Fatal(`fail to find with "host link:" string in linker output`)
2560 }
2561
2562
2563
2564 tmpdir := hostLinkLine
2565 i := strings.Index(tmpdir, `go.o"`)
2566 if i == -1 {
2567 t.Fatalf(`fail to find "go.o" in "host link:" line %q`, hostLinkLine)
2568 }
2569 tmpdir = tmpdir[:i-1]
2570 i = strings.LastIndex(tmpdir, `"`)
2571 if i == -1 {
2572 t.Fatalf(`fail to find " in "host link:" line %q`, hostLinkLine)
2573 }
2574 tmpdir = tmpdir[i+1:]
2575
2576 _, err := os.Stat(tmpdir)
2577 if err == nil {
2578 t.Fatalf("temp directory %q has not been removed", tmpdir)
2579 }
2580 if !os.IsNotExist(err) {
2581 t.Fatalf("Stat(%q) returns unexpected error: %v", tmpdir, err)
2582 }
2583 }
2584
2585
2586 func TestCoverpkgTestOnly(t *testing.T) {
2587 skipIfGccgo(t, "gccgo has no cover tool")
2588 tooSlow(t, "links and runs a test binary with coverage enabled")
2589
2590 tg := testgo(t)
2591 defer tg.cleanup()
2592 tg.parallel()
2593 tg.tempFile("src/a/a.go", `package a
2594 func F(i int) int {
2595 return i*i
2596 }`)
2597 tg.tempFile("src/atest/a_test.go", `
2598 package a_test
2599 import ( "a"; "testing" )
2600 func TestF(t *testing.T) { a.F(2) }
2601 `)
2602 tg.setenv("GOPATH", tg.path("."))
2603 tg.run("test", "-coverpkg=a", "atest")
2604 tg.grepStderrNot("no packages being tested depend on matches", "bad match message")
2605 tg.grepStdout("coverage: 100", "no coverage")
2606 }
2607
View as plain text