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 func TestBinaryOnlyPackages(t *testing.T) {
1678 tooSlow(t, "compiles several packages sequentially")
1679
1680 tg := testgo(t)
1681 defer tg.cleanup()
1682 tg.parallel()
1683 tg.makeTempdir()
1684 tg.setenv("GOPATH", tg.path("."))
1685
1686 tg.tempFile("src/p1/p1.go", `//go:binary-only-package
1687
1688 package p1
1689 `)
1690 tg.wantStale("p1", "binary-only packages are no longer supported", "p1 is binary-only, and this message should always be printed")
1691 tg.runFail("install", "p1")
1692 tg.grepStderr("binary-only packages are no longer supported", "did not report attempt to compile binary-only package")
1693
1694 tg.tempFile("src/p1/p1.go", `
1695 package p1
1696 import "fmt"
1697 func F(b bool) { fmt.Printf("hello from p1\n"); if b { F(false) } }
1698 `)
1699 tg.run("install", "p1")
1700 os.Remove(tg.path("src/p1/p1.go"))
1701 tg.mustNotExist(tg.path("src/p1/p1.go"))
1702
1703 tg.tempFile("src/p2/p2.go", `//go:binary-only-packages-are-not-great
1704
1705 package p2
1706 import "p1"
1707 func F() { p1.F(true) }
1708 `)
1709 tg.runFail("install", "p2")
1710 tg.grepStderr("no Go files", "did not complain about missing sources")
1711
1712 tg.tempFile("src/p1/missing.go", `//go:binary-only-package
1713
1714 package p1
1715 import _ "fmt"
1716 func G()
1717 `)
1718 tg.wantStale("p1", "binary-only package", "should NOT want to rebuild p1 (first)")
1719 tg.runFail("install", "p2")
1720 tg.grepStderr("p1: binary-only packages are no longer supported", "did not report error for binary-only p1")
1721
1722 tg.run("list", "-deps", "-f", "{{.ImportPath}}: {{.BinaryOnly}}", "p2")
1723 tg.grepStdout("p1: true", "p1 not listed as BinaryOnly")
1724 tg.grepStdout("p2: false", "p2 listed as BinaryOnly")
1725 }
1726
1727
1728 func TestLinkSysoFiles(t *testing.T) {
1729 if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
1730 t.Skip("not linux/amd64")
1731 }
1732
1733 tg := testgo(t)
1734 defer tg.cleanup()
1735 tg.parallel()
1736 tg.tempDir("src/syso")
1737 tg.tempFile("src/syso/a.syso", ``)
1738 tg.tempFile("src/syso/b.go", `package syso`)
1739 tg.setenv("GOPATH", tg.path("."))
1740
1741
1742
1743
1744 tg.setenv("CGO_ENABLED", "1")
1745 tg.run("list", "-f", "{{.SysoFiles}}", "syso")
1746 tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=1")
1747
1748 tg.setenv("CGO_ENABLED", "0")
1749 tg.run("list", "-f", "{{.SysoFiles}}", "syso")
1750 tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=0")
1751
1752 tg.setenv("CGO_ENABLED", "1")
1753 tg.run("list", "-msan", "-f", "{{.SysoFiles}}", "syso")
1754 tg.grepStdoutNot("a.syso", "unexpected syso file with -msan")
1755 }
1756
1757
1758 func TestGenerateUsesBuildContext(t *testing.T) {
1759 if runtime.GOOS == "windows" {
1760 t.Skip("this test won't run under Windows")
1761 }
1762
1763 tg := testgo(t)
1764 defer tg.cleanup()
1765 tg.parallel()
1766 tg.tempDir("src/gen")
1767 tg.tempFile("src/gen/gen.go", "package gen\n//go:generate echo $GOOS $GOARCH\n")
1768 tg.setenv("GOPATH", tg.path("."))
1769
1770 tg.setenv("GOOS", "linux")
1771 tg.setenv("GOARCH", "amd64")
1772 tg.run("generate", "gen")
1773 tg.grepStdout("linux amd64", "unexpected GOOS/GOARCH combination")
1774
1775 tg.setenv("GOOS", "darwin")
1776 tg.setenv("GOARCH", "arm64")
1777 tg.run("generate", "gen")
1778 tg.grepStdout("darwin arm64", "unexpected GOOS/GOARCH combination")
1779 }
1780
1781 func TestGoEnv(t *testing.T) {
1782 tg := testgo(t)
1783 tg.parallel()
1784 defer tg.cleanup()
1785 tg.setenv("GOOS", "freebsd")
1786 tg.setenv("GOARCH", "arm")
1787 tg.run("env", "GOARCH")
1788 tg.grepStdout("^arm$", "GOARCH not honored")
1789
1790 tg.run("env", "GCCGO")
1791 tg.grepStdout(".", "GCCGO unexpectedly empty")
1792
1793 tg.run("env", "CGO_CFLAGS")
1794 tg.grepStdout(".", "default CGO_CFLAGS unexpectedly empty")
1795
1796 tg.setenv("CGO_CFLAGS", "-foobar")
1797 tg.run("env", "CGO_CFLAGS")
1798 tg.grepStdout("^-foobar$", "CGO_CFLAGS not honored")
1799
1800 tg.setenv("CC", "gcc -fmust -fgo -ffaster")
1801 tg.run("env", "CC")
1802 tg.grepStdout("gcc", "CC not found")
1803 tg.run("env", "GOGCCFLAGS")
1804 tg.grepStdout("-ffaster", "CC arguments not found")
1805
1806 tg.run("env", "GOVERSION")
1807 envVersion := strings.TrimSpace(tg.stdout.String())
1808
1809 tg.run("version")
1810 cmdVersion := strings.TrimSpace(tg.stdout.String())
1811
1812
1813
1814 if cmdVersion == envVersion || !strings.Contains(cmdVersion, envVersion) {
1815 t.Fatalf("'go env GOVERSION' %q should be a shorter substring of 'go version' %q", envVersion, cmdVersion)
1816 }
1817 }
1818
1819 const (
1820 noMatchesPattern = `(?m)^ok.*\[no tests to run\]`
1821 okPattern = `(?m)^ok`
1822 )
1823
1824
1825 func TestLdBindNow(t *testing.T) {
1826 tg := testgo(t)
1827 defer tg.cleanup()
1828 tg.parallel()
1829 tg.setenv("LD_BIND_NOW", "1")
1830 tg.run("help")
1831 }
1832
1833
1834
1835 func TestConcurrentAsm(t *testing.T) {
1836 skipIfGccgo(t, "gccgo does not use cmd/asm")
1837 tg := testgo(t)
1838 defer tg.cleanup()
1839 tg.parallel()
1840 asm := `DATA ·constants<>+0x0(SB)/8,$0
1841 GLOBL ·constants<>(SB),8,$8
1842 `
1843 tg.tempFile("go/src/p/a.s", asm)
1844 tg.tempFile("go/src/p/b.s", asm)
1845 tg.tempFile("go/src/p/p.go", `package p`)
1846 tg.setenv("GOPATH", tg.path("go"))
1847 tg.run("build", "p")
1848 }
1849
1850
1851 func TestFFLAGS(t *testing.T) {
1852 testenv.MustHaveCGO(t)
1853
1854 tg := testgo(t)
1855 defer tg.cleanup()
1856 tg.parallel()
1857
1858 tg.tempFile("p/src/p/main.go", `package main
1859 // #cgo FFLAGS: -no-such-fortran-flag
1860 import "C"
1861 func main() {}
1862 `)
1863 tg.tempFile("p/src/p/a.f", `! comment`)
1864 tg.setenv("GOPATH", tg.path("p"))
1865
1866
1867
1868
1869 tg.doRun([]string{"build", "-x", "p"})
1870
1871 tg.grepStderr("no-such-fortran-flag", `missing expected "-no-such-fortran-flag"`)
1872 }
1873
1874
1875
1876 func TestDuplicateGlobalAsmSymbols(t *testing.T) {
1877 skipIfGccgo(t, "gccgo does not use cmd/asm")
1878 tooSlow(t, "links a binary with cgo dependencies")
1879 if runtime.GOARCH != "386" && runtime.GOARCH != "amd64" {
1880 t.Skipf("skipping test on %s", runtime.GOARCH)
1881 }
1882 testenv.MustHaveCGO(t)
1883
1884 tg := testgo(t)
1885 defer tg.cleanup()
1886 tg.parallel()
1887
1888 asm := `
1889 #include "textflag.h"
1890
1891 DATA sym<>+0x0(SB)/8,$0
1892 GLOBL sym<>(SB),(NOPTR+RODATA),$8
1893
1894 TEXT ·Data(SB),NOSPLIT,$0
1895 MOVB sym<>(SB), AX
1896 MOVB AX, ret+0(FP)
1897 RET
1898 `
1899 tg.tempFile("go/src/a/a.s", asm)
1900 tg.tempFile("go/src/a/a.go", `package a; func Data() uint8`)
1901 tg.tempFile("go/src/b/b.s", asm)
1902 tg.tempFile("go/src/b/b.go", `package b; func Data() uint8`)
1903 tg.tempFile("go/src/p/p.go", `
1904 package main
1905 import "a"
1906 import "b"
1907 import "C"
1908 func main() {
1909 _ = a.Data() + b.Data()
1910 }
1911 `)
1912 tg.setenv("GOPATH", tg.path("go"))
1913 exe := tg.path("p.exe")
1914 tg.creatingTemp(exe)
1915 tg.run("build", "-o", exe, "p")
1916 }
1917
1918 func copyFile(src, dst string, perm fs.FileMode) error {
1919 sf, err := os.Open(src)
1920 if err != nil {
1921 return err
1922 }
1923 defer sf.Close()
1924
1925 df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
1926 if err != nil {
1927 return err
1928 }
1929
1930 _, err = io.Copy(df, sf)
1931 err2 := df.Close()
1932 if err != nil {
1933 return err
1934 }
1935 return err2
1936 }
1937
1938 func TestNeedVersion(t *testing.T) {
1939 skipIfGccgo(t, "gccgo does not use cmd/compile")
1940 tg := testgo(t)
1941 defer tg.cleanup()
1942 tg.parallel()
1943 tg.tempFile("goversion.go", `package main; func main() {}`)
1944 path := tg.path("goversion.go")
1945 tg.setenv("TESTGO_TOOLCHAIN_VERSION", "go1.testgo")
1946 tg.runFail("run", path)
1947 tg.grepStderr("compile", "does not match go tool version")
1948 }
1949
1950 func TestBuildmodePIE(t *testing.T) {
1951 tooSlow(t, "links binaries")
1952 t.Parallel()
1953
1954 if !platform.BuildModeSupported(runtime.Compiler, "pie", runtime.GOOS, runtime.GOARCH) {
1955 t.Skipf("skipping test because buildmode=pie is not supported on %s/%s", runtime.GOOS, runtime.GOARCH)
1956 }
1957
1958 if strings.HasSuffix(testenv.Builder(), "-alpine") {
1959 t.Skip("skipping PIE tests on alpine; see https://go.dev/issues/54354")
1960 }
1961 t.Run("non-cgo", func(t *testing.T) {
1962 testBuildmodePIE(t, false, true)
1963 })
1964 t.Run("cgo", func(t *testing.T) {
1965 testenv.MustHaveCGO(t)
1966 testBuildmodePIE(t, true, true)
1967 })
1968 }
1969
1970 func TestWindowsDefaultBuildmodIsPIE(t *testing.T) {
1971 if runtime.GOOS != "windows" {
1972 t.Skip("skipping windows only test")
1973 }
1974 tooSlow(t, "links binaries")
1975 t.Parallel()
1976
1977 t.Run("non-cgo", func(t *testing.T) {
1978 testBuildmodePIE(t, false, false)
1979 })
1980 t.Run("cgo", func(t *testing.T) {
1981 testenv.MustHaveCGO(t)
1982 testBuildmodePIE(t, true, false)
1983 })
1984 }
1985
1986 func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) {
1987 tg := testgo(t)
1988 defer tg.cleanup()
1989 tg.parallel()
1990
1991 var s string
1992 if useCgo {
1993 s = `import "C";`
1994 }
1995 tg.tempFile("main.go", fmt.Sprintf(`package main;%s func main() { print("hello") }`, s))
1996 src := tg.path("main.go")
1997 obj := tg.path("main.exe")
1998 args := []string{"build"}
1999 if setBuildmodeToPIE {
2000 args = append(args, "-buildmode=pie")
2001 }
2002 args = append(args, "-o", obj, src)
2003 tg.run(args...)
2004
2005 switch runtime.GOOS {
2006 case "linux", "android", "freebsd":
2007 f, err := elf.Open(obj)
2008 if err != nil {
2009 t.Fatal(err)
2010 }
2011 defer f.Close()
2012 if f.Type != elf.ET_DYN {
2013 t.Errorf("PIE type must be ET_DYN, but %s", f.Type)
2014 }
2015 case "darwin", "ios":
2016 f, err := macho.Open(obj)
2017 if err != nil {
2018 t.Fatal(err)
2019 }
2020 defer f.Close()
2021 if f.Flags&macho.FlagDyldLink == 0 {
2022 t.Error("PIE must have DyldLink flag, but not")
2023 }
2024 if f.Flags&macho.FlagPIE == 0 {
2025 t.Error("PIE must have PIE flag, but not")
2026 }
2027 case "windows":
2028 f, err := pe.Open(obj)
2029 if err != nil {
2030 t.Fatal(err)
2031 }
2032 defer f.Close()
2033 if f.Section(".reloc") == nil {
2034 t.Error(".reloc section is not present")
2035 }
2036 if (f.FileHeader.Characteristics & pe.IMAGE_FILE_RELOCS_STRIPPED) != 0 {
2037 t.Error("IMAGE_FILE_RELOCS_STRIPPED flag is set")
2038 }
2039 var dc uint16
2040 switch oh := f.OptionalHeader.(type) {
2041 case *pe.OptionalHeader32:
2042 dc = oh.DllCharacteristics
2043 case *pe.OptionalHeader64:
2044 dc = oh.DllCharacteristics
2045 if (dc & pe.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) == 0 {
2046 t.Error("IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA flag is not set")
2047 }
2048 default:
2049 t.Fatalf("unexpected optional header type of %T", f.OptionalHeader)
2050 }
2051 if (dc & pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 {
2052 t.Error("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag is not set")
2053 }
2054 default:
2055
2056
2057 t.Skipf("skipping test: test helper does not support %s", runtime.GOOS)
2058 }
2059
2060 out, err := testenv.Command(t, obj).CombinedOutput()
2061 if err != nil {
2062 t.Fatal(err)
2063 }
2064
2065 if string(out) != "hello" {
2066 t.Errorf("got %q; want %q", out, "hello")
2067 }
2068 }
2069
2070 func TestUpxCompression(t *testing.T) {
2071 if runtime.GOOS != "linux" ||
2072 (runtime.GOARCH != "amd64" && runtime.GOARCH != "386") {
2073 t.Skipf("skipping upx test on %s/%s", runtime.GOOS, runtime.GOARCH)
2074 }
2075
2076 testenv.MustHaveExecPath(t, "upx")
2077 out, err := testenv.Command(t, "upx", "--version").CombinedOutput()
2078 if err != nil {
2079 t.Fatalf("upx --version failed: %v", err)
2080 }
2081
2082
2083
2084
2085 re := regexp.MustCompile(`([[:digit:]]+)\.([[:digit:]]+)`)
2086 upxVersion := re.FindStringSubmatch(string(out))
2087 if len(upxVersion) != 3 {
2088 t.Fatalf("bad upx version string: %s", upxVersion)
2089 }
2090
2091 major, err1 := strconv.Atoi(upxVersion[1])
2092 minor, err2 := strconv.Atoi(upxVersion[2])
2093 if err1 != nil || err2 != nil {
2094 t.Fatalf("bad upx version string: %s", upxVersion[0])
2095 }
2096
2097
2098 if (major < 3) || (major == 3 && minor < 94) {
2099 t.Skipf("skipping because upx version %v.%v is too old", major, minor)
2100 }
2101
2102 tg := testgo(t)
2103 defer tg.cleanup()
2104 tg.parallel()
2105
2106 tg.tempFile("main.go", `package main; import "fmt"; func main() { fmt.Print("hello upx") }`)
2107 src := tg.path("main.go")
2108 obj := tg.path("main")
2109 tg.run("build", "-o", obj, src)
2110
2111 out, err = testenv.Command(t, "upx", obj).CombinedOutput()
2112 if err != nil {
2113 t.Logf("executing upx\n%s\n", out)
2114 t.Fatalf("upx failed with %v", err)
2115 }
2116
2117 out, err = testenv.Command(t, obj).CombinedOutput()
2118 if err != nil {
2119 t.Logf("%s", out)
2120 t.Fatalf("running compressed go binary failed with error %s", err)
2121 }
2122 if string(out) != "hello upx" {
2123 t.Fatalf("bad output from compressed go binary:\ngot %q; want %q", out, "hello upx")
2124 }
2125 }
2126
2127 var gocacheverify = godebug.New("#gocacheverify")
2128
2129 func TestCacheListStale(t *testing.T) {
2130 tooSlow(t, "links a binary")
2131 if gocacheverify.Value() == "1" {
2132 t.Skip("GODEBUG gocacheverify")
2133 }
2134
2135 tg := testgo(t)
2136 defer tg.cleanup()
2137 tg.parallel()
2138 tg.makeTempdir()
2139 tg.setenv("GOCACHE", tg.path("cache"))
2140 tg.tempFile("gopath/src/p/p.go", "package p; import _ \"q\"; func F(){}\n")
2141 tg.tempFile("gopath/src/q/q.go", "package q; func F(){}\n")
2142 tg.tempFile("gopath/src/m/m.go", "package main; import _ \"q\"; func main(){}\n")
2143
2144 tg.setenv("GOPATH", tg.path("gopath"))
2145 tg.run("install", "p", "m")
2146 tg.run("list", "-f={{.ImportPath}} {{.Stale}}", "m", "q", "p")
2147 tg.grepStdout("^m false", "m should not be stale")
2148 tg.grepStdout("^q true", "q should be stale")
2149 tg.grepStdout("^p false", "p should not be stale")
2150 }
2151
2152 func TestCacheCoverage(t *testing.T) {
2153 tooSlow(t, "links and runs a test binary with coverage enabled")
2154 if gocacheverify.Value() == "1" {
2155 t.Skip("GODEBUG gocacheverify")
2156 }
2157
2158 tg := testgo(t)
2159 defer tg.cleanup()
2160 tg.parallel()
2161 tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
2162 tg.makeTempdir()
2163
2164 tg.setenv("GOCACHE", tg.path("c1"))
2165 tg.run("test", "-cover", "-short", "strings")
2166 tg.run("test", "-cover", "-short", "math", "strings")
2167 }
2168
2169 func TestIssue22531(t *testing.T) {
2170 tooSlow(t, "links binaries")
2171 if gocacheverify.Value() == "1" {
2172 t.Skip("GODEBUG gocacheverify")
2173 }
2174
2175 tg := testgo(t)
2176 defer tg.cleanup()
2177 tg.parallel()
2178 tg.makeTempdir()
2179 tg.setenv("GOPATH", tg.tempdir)
2180 tg.setenv("GOCACHE", tg.path("cache"))
2181 tg.tempFile("src/m/main.go", "package main /* c1 */; func main() {}\n")
2182 tg.run("install", "-x", "m")
2183 tg.run("list", "-f", "{{.Stale}}", "m")
2184 tg.grepStdout("false", "reported m as stale after install")
2185 tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix))
2186
2187
2188
2189
2190
2191
2192 tg.tempFile("src/m/main.go", "package main /* c2 */; func main() {}\n")
2193 tg.run("install", "-x", "m")
2194 tg.run("list", "-f", "{{.Stale}}", "m")
2195 tg.grepStdout("false", "reported m as stale after reinstall")
2196 tg.run("tool", "buildid", tg.path("bin/m"+exeSuffix))
2197 }
2198
2199 func TestIssue22596(t *testing.T) {
2200 tooSlow(t, "links binaries")
2201 if gocacheverify.Value() == "1" {
2202 t.Skip("GODEBUG gocacheverify")
2203 }
2204
2205 tg := testgo(t)
2206 defer tg.cleanup()
2207 tg.parallel()
2208 tg.makeTempdir()
2209 tg.setenv("GOCACHE", tg.path("cache"))
2210 tg.tempFile("gopath1/src/p/p.go", "package p; func F(){}\n")
2211 tg.tempFile("gopath2/src/p/p.go", "package p; func F(){}\n")
2212
2213 tg.setenv("GOPATH", tg.path("gopath1"))
2214 tg.run("list", "-f={{.Target}}", "p")
2215 target1 := strings.TrimSpace(tg.getStdout())
2216 tg.run("install", "p")
2217 tg.wantNotStale("p", "", "p stale after install")
2218
2219 tg.setenv("GOPATH", tg.path("gopath2"))
2220 tg.run("list", "-f={{.Target}}", "p")
2221 target2 := strings.TrimSpace(tg.getStdout())
2222 tg.must(os.MkdirAll(filepath.Dir(target2), 0777))
2223 tg.must(copyFile(target1, target2, 0666))
2224 tg.wantStale("p", "build ID mismatch", "p not stale after copy from gopath1")
2225 tg.run("install", "p")
2226 tg.wantNotStale("p", "", "p stale after install2")
2227 }
2228
2229 func TestTestCache(t *testing.T) {
2230 tooSlow(t, "links and runs test binaries")
2231 if gocacheverify.Value() == "1" {
2232 t.Skip("GODEBUG gocacheverify")
2233 }
2234
2235 tg := testgo(t)
2236 defer tg.cleanup()
2237 tg.parallel()
2238 tg.makeTempdir()
2239 tg.setenv("GOPATH", tg.tempdir)
2240 tg.setenv("GOCACHE", tg.path("cache"))
2241
2242
2243
2244 t.Log("\n\nINITIAL\n\n")
2245
2246 tg.tempFile("src/p1/p1.go", "package p1\nvar X = 1\n")
2247 tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\nvar X = 1\n")
2248 tg.tempFile("src/t/t1/t1_test.go", "package t\nimport \"testing\"\nfunc Test1(*testing.T) {}\n")
2249 tg.tempFile("src/t/t2/t2_test.go", "package t\nimport _ \"p1\"\nimport \"testing\"\nfunc Test2(*testing.T) {}\n")
2250 tg.tempFile("src/t/t3/t3_test.go", "package t\nimport \"p1\"\nimport \"testing\"\nfunc Test3(t *testing.T) {t.Log(p1.X)}\n")
2251 tg.tempFile("src/t/t4/t4_test.go", "package t\nimport \"p2\"\nimport \"testing\"\nfunc Test4(t *testing.T) {t.Log(p2.X)}")
2252 tg.run("test", "-x", "-v", "-short", "t/...")
2253
2254 t.Log("\n\nREPEAT\n\n")
2255
2256 tg.run("test", "-x", "-v", "-short", "t/...")
2257 tg.grepStdout(`ok \tt/t1\t\(cached\)`, "did not cache t1")
2258 tg.grepStdout(`ok \tt/t2\t\(cached\)`, "did not cache t2")
2259 tg.grepStdout(`ok \tt/t3\t\(cached\)`, "did not cache t3")
2260 tg.grepStdout(`ok \tt/t4\t\(cached\)`, "did not cache t4")
2261 tg.grepStderrNot(`[\\/](compile|gccgo) `, "incorrectly ran compiler")
2262 tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker")
2263 tg.grepStderrNot(`p[0-9]\.test`, "incorrectly ran test")
2264
2265 t.Log("\n\nCOMMENT\n\n")
2266
2267
2268
2269 tg.tempFile("src/p1/p1.go", "package p1\nvar X = 01\n")
2270 tg.run("test", "-p=1", "-x", "-v", "-short", "t/...")
2271 tg.grepStdout(`ok \tt/t1\t\(cached\)`, "did not cache t1")
2272 tg.grepStdout(`ok \tt/t2\t\(cached\)`, "did not cache t2")
2273 tg.grepStdout(`ok \tt/t3\t\(cached\)`, "did not cache t3")
2274 tg.grepStdout(`ok \tt/t4\t\(cached\)`, "did not cache t4")
2275 tg.grepStderrNot(`([\\/](compile|gccgo) ).*t[0-9]_test\.go`, "incorrectly ran compiler")
2276 tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker")
2277 tg.grepStderrNot(`t[0-9]\.test.*test\.short`, "incorrectly ran test")
2278
2279 t.Log("\n\nCHANGE\n\n")
2280
2281
2282 tg.tempFile("src/p1/p1.go", "package p1\nvar X = 02\n")
2283 tg.run("test", "-p=1", "-x", "-v", "-short", "t/...")
2284
2285
2286 tg.grepStderr(`([\\/]compile|gccgo).*p2.go`, "did not recompile p2")
2287
2288
2289 tg.grepStderrNot(`([\\/]compile|gccgo).*t1_test.go`, "incorrectly recompiled t1")
2290 tg.grepStderrNot(`([\\/]link|gccgo).*t1_test`, "incorrectly relinked t1_test")
2291 tg.grepStdout(`ok \tt/t1\t\(cached\)`, "did not cache t/t1")
2292
2293
2294
2295
2296 tg.grepStderr(`([\\/]compile|gccgo).*t2_test.go`, "did not recompile t2")
2297 tg.grepStderr(`([\\/]link|gccgo).*t2\.test`, "did not relink t2_test")
2298
2299
2300 if runtime.Compiler != "gccgo" {
2301 tg.grepStdout(`ok \tt/t2\t\(cached\)`, "did not cache t/t2")
2302 }
2303
2304
2305 tg.grepStderr(`([\\/]compile|gccgo).*t3_test.go`, "did not recompile t3")
2306 tg.grepStderr(`([\\/]link|gccgo).*t3\.test`, "did not relink t3_test")
2307 tg.grepStderr(`t3\.test.*-test.short`, "did not rerun t3_test")
2308 tg.grepStdoutNot(`ok \tt/t3\t\(cached\)`, "reported cached t3_test result")
2309
2310
2311
2312 tg.grepStderrNot(`([\\/]compile|gccgo).*t4_test.go`, "incorrectly recompiled t4")
2313 tg.grepStderr(`([\\/]link|gccgo).*t4\.test`, "did not relink t4_test")
2314
2315
2316 if runtime.Compiler != "gccgo" {
2317 tg.grepStdout(`ok \tt/t4\t\(cached\)`, "did not cache t/t4")
2318 }
2319 }
2320
2321 func TestTestSkipVetAfterFailedBuild(t *testing.T) {
2322 tg := testgo(t)
2323 defer tg.cleanup()
2324 tg.parallel()
2325
2326 tg.tempFile("x_test.go", `package x
2327 func f() {
2328 return 1
2329 }
2330 `)
2331
2332 tg.runFail("test", tg.path("x_test.go"))
2333 tg.grepStderrNot(`vet`, "vet should be skipped after the failed build")
2334 }
2335
2336 func TestTestVetRebuild(t *testing.T) {
2337 tooSlow(t, "links and runs test binaries")
2338
2339 tg := testgo(t)
2340 defer tg.cleanup()
2341 tg.parallel()
2342
2343
2344
2345
2346
2347 tg.tempFile("src/a/a.go", `package a
2348 import "b"
2349 type Type struct{}
2350 func (*Type) M() b.T {return 0}
2351 `)
2352 tg.tempFile("src/b/b.go", `package b
2353 type T int
2354 type I interface {M() T}
2355 `)
2356 tg.tempFile("src/b/export_test.go", `package b
2357 func (*T) Method() *T { return nil }
2358 `)
2359 tg.tempFile("src/b/b_test.go", `package b_test
2360 import (
2361 "testing"
2362 "a"
2363 . "b"
2364 )
2365 func TestBroken(t *testing.T) {
2366 x := new(T)
2367 x.Method()
2368 _ = new(a.Type)
2369 }
2370 `)
2371
2372 tg.setenv("GOPATH", tg.path("."))
2373 tg.run("test", "b")
2374 tg.run("vet", "b")
2375 }
2376
2377 func TestInstallDeps(t *testing.T) {
2378 tooSlow(t, "links a binary")
2379
2380 tg := testgo(t)
2381 defer tg.cleanup()
2382 tg.parallel()
2383 tg.makeTempdir()
2384 tg.setenv("GOPATH", tg.tempdir)
2385
2386 tg.tempFile("src/p1/p1.go", "package p1\nvar X = 1\n")
2387 tg.tempFile("src/p2/p2.go", "package p2\nimport _ \"p1\"\n")
2388 tg.tempFile("src/main1/main.go", "package main\nimport _ \"p2\"\nfunc main() {}\n")
2389
2390 tg.run("list", "-f={{.Target}}", "p1")
2391 p1 := strings.TrimSpace(tg.getStdout())
2392 tg.run("list", "-f={{.Target}}", "p2")
2393 p2 := strings.TrimSpace(tg.getStdout())
2394 tg.run("list", "-f={{.Target}}", "main1")
2395 main1 := strings.TrimSpace(tg.getStdout())
2396
2397 tg.run("install", "main1")
2398
2399 tg.mustExist(main1)
2400 tg.mustNotExist(p2)
2401 tg.mustNotExist(p1)
2402
2403 tg.run("install", "p2")
2404 tg.mustExist(p2)
2405 tg.mustNotExist(p1)
2406 }
2407
2408
2409 func TestImportPath(t *testing.T) {
2410 tooSlow(t, "links and runs a test binary")
2411
2412 tg := testgo(t)
2413 defer tg.cleanup()
2414 tg.parallel()
2415
2416 tg.tempFile("src/a/a.go", `
2417 package main
2418
2419 import (
2420 "log"
2421 p "a/p-1.0"
2422 )
2423
2424 func main() {
2425 if !p.V {
2426 log.Fatal("false")
2427 }
2428 }`)
2429
2430 tg.tempFile("src/a/a_test.go", `
2431 package main_test
2432
2433 import (
2434 p "a/p-1.0"
2435 "testing"
2436 )
2437
2438 func TestV(t *testing.T) {
2439 if !p.V {
2440 t.Fatal("false")
2441 }
2442 }`)
2443
2444 tg.tempFile("src/a/p-1.0/p.go", `
2445 package p
2446
2447 var V = true
2448
2449 func init() {}
2450 `)
2451
2452 tg.setenv("GOPATH", tg.path("."))
2453 tg.run("build", "-o", tg.path("a.exe"), "a")
2454 tg.run("test", "a")
2455 }
2456
2457 func TestBadCommandLines(t *testing.T) {
2458 tg := testgo(t)
2459 defer tg.cleanup()
2460 tg.parallel()
2461
2462 tg.tempFile("src/x/x.go", "package x\n")
2463 tg.setenv("GOPATH", tg.path("."))
2464
2465 tg.run("build", "x")
2466
2467 tg.tempFile("src/x/@y.go", "package x\n")
2468 tg.runFail("build", "x")
2469 tg.grepStderr("invalid input file name \"@y.go\"", "did not reject @y.go")
2470 tg.must(os.Remove(tg.path("src/x/@y.go")))
2471
2472 tg.tempFile("src/x/-y.go", "package x\n")
2473 tg.runFail("build", "x")
2474 tg.grepStderr("invalid input file name \"-y.go\"", "did not reject -y.go")
2475 tg.must(os.Remove(tg.path("src/x/-y.go")))
2476
2477 if runtime.Compiler == "gccgo" {
2478 tg.runFail("build", "-gccgoflags=all=@x", "x")
2479 } else {
2480 tg.runFail("build", "-gcflags=all=@x", "x")
2481 }
2482 tg.grepStderr("invalid command-line argument @x in command", "did not reject @x during exec")
2483
2484 tg.tempFile("src/@x/x.go", "package x\n")
2485 tg.setenv("GOPATH", tg.path("."))
2486 tg.runFail("build", "@x")
2487 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")
2488
2489 tg.tempFile("src/@x/y/y.go", "package y\n")
2490 tg.setenv("GOPATH", tg.path("."))
2491 tg.runFail("build", "@x/y")
2492 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")
2493
2494 tg.tempFile("src/-x/x.go", "package x\n")
2495 tg.setenv("GOPATH", tg.path("."))
2496 tg.runFail("build", "--", "-x")
2497 tg.grepStderr("invalid import path \"-x\"", "did not reject -x import path")
2498
2499 tg.tempFile("src/-x/y/y.go", "package y\n")
2500 tg.setenv("GOPATH", tg.path("."))
2501 tg.runFail("build", "--", "-x/y")
2502 tg.grepStderr("invalid import path \"-x/y\"", "did not reject -x/y import path")
2503 }
2504
2505 func TestTwoPkgConfigs(t *testing.T) {
2506 testenv.MustHaveCGO(t)
2507 if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
2508 t.Skipf("no shell scripts on %s", runtime.GOOS)
2509 }
2510 tooSlow(t, "builds a package with cgo dependencies")
2511
2512 tg := testgo(t)
2513 defer tg.cleanup()
2514 tg.parallel()
2515 tg.tempFile("src/x/a.go", `package x
2516 // #cgo pkg-config: --static a
2517 import "C"
2518 `)
2519 tg.tempFile("src/x/b.go", `package x
2520 // #cgo pkg-config: --static a
2521 import "C"
2522 `)
2523 tg.tempFile("pkg-config.sh", `#!/bin/sh
2524 echo $* >>`+tg.path("pkg-config.out"))
2525 tg.must(os.Chmod(tg.path("pkg-config.sh"), 0755))
2526 tg.setenv("GOPATH", tg.path("."))
2527 tg.setenv("PKG_CONFIG", tg.path("pkg-config.sh"))
2528 tg.run("build", "x")
2529 out, err := os.ReadFile(tg.path("pkg-config.out"))
2530 tg.must(err)
2531 out = bytes.TrimSpace(out)
2532 want := "--cflags --static --static -- a a\n--libs --static --static -- a a"
2533 if !bytes.Equal(out, []byte(want)) {
2534 t.Errorf("got %q want %q", out, want)
2535 }
2536 }
2537
2538 func TestCgoCache(t *testing.T) {
2539 testenv.MustHaveCGO(t)
2540 tooSlow(t, "builds a package with cgo dependencies")
2541
2542 tg := testgo(t)
2543 defer tg.cleanup()
2544 tg.parallel()
2545 tg.tempFile("src/x/a.go", `package main
2546 // #ifndef VAL
2547 // #define VAL 0
2548 // #endif
2549 // int val = VAL;
2550 import "C"
2551 import "fmt"
2552 func main() { fmt.Println(C.val) }
2553 `)
2554 tg.setenv("GOPATH", tg.path("."))
2555 exe := tg.path("x.exe")
2556 tg.run("build", "-o", exe, "x")
2557 tg.setenv("CGO_LDFLAGS", "-lnosuchlibraryexists")
2558 tg.runFail("build", "-o", exe, "x")
2559 tg.grepStderr(`nosuchlibraryexists`, "did not run linker with changed CGO_LDFLAGS")
2560 }
2561
2562
2563 func TestFilepathUnderCwdFormat(t *testing.T) {
2564 tg := testgo(t)
2565 defer tg.cleanup()
2566 tg.parallel()
2567 tg.run("test", "-x", "-cover", "log")
2568 tg.grepStderrNot(`\.log\.cover\.go`, "-x output should contain correctly formatted filepath under cwd")
2569 }
2570
2571
2572 func TestDontReportRemoveOfEmptyDir(t *testing.T) {
2573 tg := testgo(t)
2574 defer tg.cleanup()
2575 tg.parallel()
2576 tg.tempFile("src/a/a.go", `package a`)
2577 tg.setenv("GOPATH", tg.path("."))
2578 tg.run("install", "-x", "a")
2579 tg.run("install", "-x", "a")
2580
2581
2582 if bytes.Count(tg.stdout.Bytes(), []byte{'\n'})+bytes.Count(tg.stderr.Bytes(), []byte{'\n'}) > 1 {
2583 t.Error("unnecessary output when installing installed package")
2584 }
2585 }
2586
2587
2588 func TestLinkerTmpDirIsDeleted(t *testing.T) {
2589 skipIfGccgo(t, "gccgo does not use cmd/link")
2590 testenv.MustHaveCGO(t)
2591 tooSlow(t, "builds a package with cgo dependencies")
2592
2593 tg := testgo(t)
2594 defer tg.cleanup()
2595 tg.parallel()
2596 tg.tempFile("a.go", `package main; import "C"; func main() {}`)
2597 tg.run("build", "-ldflags", "-v", "-o", os.DevNull, tg.path("a.go"))
2598
2599 stderr := tg.getStderr()
2600 var hostLinkLine string
2601 for _, line := range strings.Split(stderr, "\n") {
2602 if !strings.Contains(line, "host link:") {
2603 continue
2604 }
2605 hostLinkLine = line
2606 break
2607 }
2608 if hostLinkLine == "" {
2609 t.Fatal(`fail to find with "host link:" string in linker output`)
2610 }
2611
2612
2613
2614 tmpdir := hostLinkLine
2615 i := strings.Index(tmpdir, `go.o"`)
2616 if i == -1 {
2617 t.Fatalf(`fail to find "go.o" in "host link:" line %q`, hostLinkLine)
2618 }
2619 tmpdir = tmpdir[:i-1]
2620 i = strings.LastIndex(tmpdir, `"`)
2621 if i == -1 {
2622 t.Fatalf(`fail to find " in "host link:" line %q`, hostLinkLine)
2623 }
2624 tmpdir = tmpdir[i+1:]
2625
2626 _, err := os.Stat(tmpdir)
2627 if err == nil {
2628 t.Fatalf("temp directory %q has not been removed", tmpdir)
2629 }
2630 if !os.IsNotExist(err) {
2631 t.Fatalf("Stat(%q) returns unexpected error: %v", tmpdir, err)
2632 }
2633 }
2634
2635
2636 func TestCoverpkgTestOnly(t *testing.T) {
2637 skipIfGccgo(t, "gccgo has no cover tool")
2638 tooSlow(t, "links and runs a test binary with coverage enabled")
2639
2640 tg := testgo(t)
2641 defer tg.cleanup()
2642 tg.parallel()
2643 tg.tempFile("src/a/a.go", `package a
2644 func F(i int) int {
2645 return i*i
2646 }`)
2647 tg.tempFile("src/atest/a_test.go", `
2648 package a_test
2649 import ( "a"; "testing" )
2650 func TestF(t *testing.T) { a.F(2) }
2651 `)
2652 tg.setenv("GOPATH", tg.path("."))
2653 tg.run("test", "-coverpkg=a", "atest")
2654 tg.grepStderrNot("no packages being tested depend on matches", "bad match message")
2655 tg.grepStdout("coverage: 100", "no coverage")
2656 }
2657
View as plain text