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