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