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