github.com/sc0rp1us/gb@v0.4.1-0.20160319180011-4ba8cf1baa5a/cmd/gb/gb_test.go (about) 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 5 package main_test 6 7 // gb functional tests adapted from src/cmd/go/go_test.go 8 9 import ( 10 "bytes" 11 "flag" 12 "fmt" 13 "go/format" 14 "io" 15 "io/ioutil" 16 "log" 17 "os" 18 "os/exec" 19 "path/filepath" 20 "regexp" 21 "runtime" 22 "strings" 23 "testing" 24 ) 25 26 var ( 27 canRun = true // whether we can run go or ./testgb 28 canRace = false // whether we can run the race detector 29 canCgo = false // whether we can use cgo 30 31 exeSuffix string // ".exe" on Windows 32 33 skipExternalBuilder = false // skip external tests on this builder 34 35 testgb string = "testgb" 36 ) 37 38 func init() { 39 switch runtime.GOOS { 40 case "android", "nacl": 41 canRun = false 42 case "darwin": 43 switch runtime.GOARCH { 44 case "arm", "arm64": 45 canRun = false 46 } 47 } 48 49 switch runtime.GOOS { 50 case "windows": 51 exeSuffix = ".exe" 52 } 53 testgb += exeSuffix 54 } 55 56 // The TestMain function creates a gb command for testing purposes and 57 // deletes it after the tests have been run. 58 func TestMain(m *testing.M) { 59 flag.Parse() 60 61 if canRun { 62 dir, err := ioutil.TempDir("", "testgb") 63 if err != nil { 64 fmt.Fprintf(os.Stderr, "cannot create temporary directory: %v", err) 65 os.Exit(2) 66 } 67 testgb = filepath.Join(dir, testgb) 68 locations := [][]string{ 69 []string{runtime.GOROOT(), "bin", "go"}, 70 []string{runtime.GOROOT(), "..", "bin", "go"}, 71 []string{runtime.GOROOT(), "..", "..", "bin", "go"}, 72 } 73 ok := false 74 for _, loc := range locations { 75 out, err := exec.Command(filepath.Join(loc...), "build", "-o", testgb).CombinedOutput() 76 if err == nil { 77 ok = true 78 break 79 } 80 log.Printf("building testgb failed: %v\n%s", err, out) 81 } 82 if !ok { 83 os.Exit(2) 84 } 85 _, err = os.Stat(filepath.Join(runtime.GOROOT(), "pkg", fmt.Sprintf("%s_%s_race", runtime.GOOS, runtime.GOARCH), "runtime.a")) 86 switch { 87 case os.IsNotExist(err): 88 log.Printf("go installation at %s is missing race support", runtime.GOROOT()) 89 case runtime.GOARCH == "amd64": 90 canRace = runtime.GOOS == "linux" || runtime.GOOS == "freebsd" || runtime.GOOS == "windows" || runtime.GOOS == "darwin" 91 } 92 } 93 94 // Don't let these environment variables confuse the test. 95 os.Unsetenv("GOBIN") 96 os.Unsetenv("GOPATH") 97 os.Unsetenv("DEBUG") 98 99 r := m.Run() 100 os.Exit(r) 101 } 102 103 // T manage a single run of the testgb binary. 104 type T struct { 105 *testing.T 106 temps []string 107 wd string 108 env []string 109 tempdir string 110 ran bool 111 stdin io.Reader 112 stdout, stderr bytes.Buffer 113 } 114 115 // must gives a fatal error if err is not nil. 116 func (t *T) must(err error) { 117 if err != nil { 118 t.Fatal(err) 119 } 120 } 121 122 // check gives a test non-fatal error if err is not nil. 123 func (t *T) check(err error) { 124 if err != nil { 125 t.Error(err) 126 } 127 } 128 129 // pwd returns the current directory. 130 func (t *T) pwd() string { 131 wd, err := os.Getwd() 132 if err != nil { 133 t.Fatalf("could not get working directory: %v", err) 134 } 135 return wd 136 } 137 138 // cd changes the current directory to the named directory. extra args 139 // are passed through filepath.Join before cd. 140 func (t *T) cd(dir string, extra ...string) { 141 if t.wd == "" { 142 t.wd = t.pwd() 143 } 144 v := append([]string{dir}, extra...) 145 dir = filepath.Join(v...) 146 abs, err := filepath.Abs(dir) 147 t.must(os.Chdir(dir)) 148 if err == nil { 149 t.setenv("PWD", abs) 150 } 151 } 152 153 // setenv sets an environment variable to use when running the test go 154 // command. 155 func (t *T) setenv(name, val string) { 156 t.unsetenv(name) 157 t.env = append(t.env, name+"="+val) 158 } 159 160 // unsetenv removes an environment variable. 161 func (t *T) unsetenv(name string) { 162 if t.env == nil { 163 t.env = append([]string(nil), os.Environ()...) 164 } 165 for i, v := range t.env { 166 if strings.HasPrefix(v, name+"=") { 167 t.env = append(t.env[:i], t.env[i+1:]...) 168 break 169 } 170 } 171 } 172 173 // doRun runs the test go command, recording stdout and stderr and 174 // returning exit status. 175 func (t *T) doRun(args []string) error { 176 if !canRun { 177 t.Fatal("T.doRun called but canRun false") 178 } 179 t.Logf("running %v %v", testgb, args) 180 cmd := exec.Command(testgb, args...) 181 t.stdout.Reset() 182 t.stderr.Reset() 183 cmd.Stdin = t.stdin 184 cmd.Stdout = &t.stdout 185 cmd.Stderr = &t.stderr 186 cmd.Env = t.env 187 status := cmd.Run() 188 if t.stdout.Len() > 0 { 189 t.Log("standard output:") 190 t.Log(t.stdout.String()) 191 } 192 if t.stderr.Len() > 0 { 193 t.Log("standard error:") 194 t.Log(t.stderr.String()) 195 } 196 t.ran = true 197 return status 198 } 199 200 // run runs the test go command, and expects it to succeed. 201 func (t *T) run(args ...string) { 202 if status := t.doRun(args); status != nil { 203 t.Logf("gb %v failed unexpectedly: %v", args, status) 204 t.FailNow() 205 } 206 } 207 208 // runFail runs the test go command, and expects it to fail. 209 func (t *T) runFail(args ...string) { 210 if status := t.doRun(args); status == nil { 211 t.Fatal(testgb, "succeeded unexpectedly") 212 } else { 213 t.Log(testgb, "failed as expected:", status) 214 } 215 } 216 217 // getStdout returns standard output of the testgb run as a string. 218 func (t *T) getStdout() string { 219 if !t.ran { 220 t.Fatal("internal testsuite error: stdout called before run") 221 } 222 return t.stdout.String() 223 } 224 225 // getStderr returns standard error of the testgb run as a string. 226 func (t *T) getStderr() string { 227 if !t.ran { 228 t.Fatal("internal testsuite error: stdout called before run") 229 } 230 return t.stderr.String() 231 } 232 233 // doGrepMatch looks for a regular expression in a buffer, and returns 234 // whether it is found. The regular expression is matched against 235 // each line separately, as with the grep command. 236 func (t *T) doGrepMatch(match string, b *bytes.Buffer) bool { 237 if !t.ran { 238 t.Fatal("internal testsuite error: grep called before run") 239 } 240 re := regexp.MustCompile(match) 241 for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) { 242 if re.Match(ln) { 243 return true 244 } 245 } 246 return false 247 } 248 249 // doGrep looks for a regular expression in a buffer and fails if it 250 // is not found. The name argument is the name of the output we are 251 // searching, "output" or "error". The msg argument is logged on 252 // failure. 253 func (t *T) doGrep(match string, b *bytes.Buffer, name, msg string) { 254 if !t.doGrepMatch(match, b) { 255 t.Log(msg) 256 t.Logf("pattern %v not found in standard %s", match, name) 257 t.FailNow() 258 } 259 } 260 261 // grepStdout looks for a regular expression in the test run's 262 // standard output and fails, logging msg, if it is not found. 263 func (t *T) grepStdout(match, msg string) { 264 t.doGrep(match, &t.stdout, "output", msg) 265 } 266 267 // grepStderr looks for a regular expression in the test run's 268 // standard error and fails, logging msg, if it is not found. 269 func (t *T) grepStderr(match, msg string) { 270 t.doGrep(match, &t.stderr, "error", msg) 271 } 272 273 // grepBoth looks for a regular expression in the test run's standard 274 // output or stand error and fails, logging msg, if it is not found. 275 func (t *T) grepBoth(match, msg string) { 276 if !t.doGrepMatch(match, &t.stdout) && !t.doGrepMatch(match, &t.stderr) { 277 t.Log(msg) 278 t.Logf("pattern %v not found in standard output or standard error", match) 279 t.FailNow() 280 } 281 } 282 283 // doGrepNot looks for a regular expression in a buffer and fails if 284 // it is found. The name and msg arguments are as for doGrep. 285 func (t *T) doGrepNot(match string, b *bytes.Buffer, name, msg string) { 286 if t.doGrepMatch(match, b) { 287 t.Log(msg) 288 t.Logf("pattern %v found unexpectedly in standard %s", match, name) 289 t.FailNow() 290 } 291 } 292 293 // grepStdoutNot looks for a regular expression in the test run's 294 // standard output and fails, logging msg, if it is found. 295 func (t *T) grepStdoutNot(match, msg string) { 296 t.doGrepNot(match, &t.stdout, "output", msg) 297 } 298 299 // grepStderrNot looks for a regular expression in the test run's 300 // standard error and fails, logging msg, if it is found. 301 func (t *T) grepStderrNot(match, msg string) { 302 t.doGrepNot(match, &t.stderr, "error", msg) 303 } 304 305 // grepBothNot looks for a regular expression in the test run's 306 // standard output or stand error and fails, logging msg, if it is 307 // found. 308 func (t *T) grepBothNot(match, msg string) { 309 if t.doGrepMatch(match, &t.stdout) || t.doGrepMatch(match, &t.stderr) { 310 t.Log(msg) 311 t.Fatalf("pattern %v found unexpectedly in standard output or standard error", match) 312 } 313 } 314 315 // doGrepCount counts the number of times a regexp is seen in a buffer. 316 func (t *T) doGrepCount(match string, b *bytes.Buffer) int { 317 if !t.ran { 318 t.Fatal("internal testsuite error: doGrepCount called before run") 319 } 320 re := regexp.MustCompile(match) 321 c := 0 322 for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) { 323 if re.Match(ln) { 324 c++ 325 } 326 } 327 return c 328 } 329 330 // grepCountStdout returns the number of times a regexp is seen in 331 // standard output. 332 func (t *T) grepCountStdout(match string) int { 333 return t.doGrepCount(match, &t.stdout) 334 } 335 336 // grepCountStderr returns the number of times a regexp is seen in 337 // standard error. 338 func (t *T) grepCountStderr(match string) int { 339 return t.doGrepCount(match, &t.stderr) 340 } 341 342 // grepCountBoth returns the number of times a regexp is seen in both 343 // standard output and standard error. 344 func (t *T) grepCountBoth(match string) int { 345 return t.doGrepCount(match, &t.stdout) + t.doGrepCount(match, &t.stderr) 346 } 347 348 // creatingTemp records that the test plans to create a temporary file 349 // or directory. If the file or directory exists already, it will be 350 // removed. When the test completes, the file or directory will be 351 // removed if it exists. 352 func (t *T) creatingTemp(path string) { 353 if filepath.IsAbs(path) && !strings.HasPrefix(path, t.tempdir) { 354 t.Fatal("internal testsuite error: creatingTemp(%q) with absolute path not in temporary directory", path) 355 } 356 // If we have changed the working directory, make sure we have 357 // an absolute path, because we are going to change directory 358 // back before we remove the temporary. 359 if t.wd != "" && !filepath.IsAbs(path) { 360 path = filepath.Join(t.pwd(), path) 361 } 362 t.must(os.RemoveAll(path)) 363 t.temps = append(t.temps, path) 364 } 365 366 // makeTempdir makes a temporary directory for a run of testgb. If 367 // the temporary directory was already created, this does nothing. 368 func (t *T) makeTempdir() { 369 if t.tempdir == "" { 370 var err error 371 t.tempdir, err = ioutil.TempDir("", "testgb") 372 t.must(err) 373 t.tempdir, err = filepath.EvalSymlinks(t.tempdir) // resolve OSX's stupid symlinked /tmp 374 t.must(err) 375 } 376 } 377 378 // tempFile adds a temporary file for a run of testgb. 379 func (t *T) tempFile(path, contents string) { 380 t.makeTempdir() 381 t.must(os.MkdirAll(filepath.Join(t.tempdir, filepath.Dir(path)), 0755)) 382 bytes := []byte(contents) 383 if strings.HasSuffix(path, ".go") { 384 formatted, err := format.Source(bytes) 385 if err == nil { 386 bytes = formatted 387 } 388 } 389 t.must(ioutil.WriteFile(filepath.Join(t.tempdir, path), bytes, 0644)) 390 } 391 392 // tempDir adds a temporary directory for a run of testgb. 393 func (t *T) tempDir(path string) string { 394 t.makeTempdir() 395 path = filepath.Join(t.tempdir, path) 396 if err := os.MkdirAll(path, 0755); err != nil && !os.IsExist(err) { 397 t.Fatal(err) 398 } 399 return path 400 } 401 402 // symlink adds a symlink from src to dst. 403 func (t *T) symlink(src, dst string) string { 404 t.makeTempdir() 405 src = filepath.Join(t.tempdir, src) 406 dst = filepath.Join(t.tempdir, dst) 407 t.must(os.Symlink(src, dst)) 408 return dst 409 } 410 411 // path returns the absolute pathname to file with the temporary 412 // directory. 413 func (t *T) path(names ...string) string { 414 if t.tempdir == "" { 415 t.Fatalf("internal testsuite error: path(%q) with no tempdir", filepath.Join(names...)) 416 } 417 if len(names) == 0 || names[0] == "." { 418 return t.tempdir 419 } 420 return filepath.Join(append([]string{t.tempdir}, names...)...) 421 } 422 423 // mustExist fails if path does not exists. 424 func (t *T) mustExist(path string) { 425 if _, err := os.Stat(path); err != nil { 426 t.Fatalf("%s does not exist (%v)", path, err) 427 } 428 } 429 430 // mustNotExist fails if path exists. 431 func (t *T) mustNotExist(path string) { 432 if _, err := os.Stat(path); err == nil || !os.IsNotExist(err) { 433 t.Fatalf("%s exists but should not (%v)", path, err) 434 } 435 } 436 437 // mustBeEmpty fails if root is not a directory or is not empty. 438 func (t *T) mustBeEmpty(root string) { 439 fi, err := os.Stat(root) 440 if err != nil { 441 t.Fatalf("failed to stat: %s: %v", root, err) 442 } 443 if !fi.IsDir() { 444 t.Fatalf("%s exists but is not a directory", root) 445 } 446 var found []string 447 fn := func(path string, info os.FileInfo, err error) error { 448 if path == root { 449 return nil 450 } 451 if err != nil { 452 t.Fatalf("error during walk at %s: %v", path, err) 453 } 454 found = append(found, path) 455 return nil 456 } 457 err = filepath.Walk(root, fn) 458 if len(found) > 0 { 459 t.Fatalf("expected %s to be empty, found %s", root, found) 460 } 461 } 462 463 // wantExecutable fails with msg if path is not executable. 464 func (t *T) wantExecutable(path, msg string) { 465 if st, err := os.Stat(path); err != nil { 466 if !os.IsNotExist(err) { 467 t.Log(err) 468 } 469 t.Fatal(msg) 470 } else { 471 if runtime.GOOS != "windows" && st.Mode()&0111 == 0 { 472 t.Fatalf("binary %s exists but is not executable", path) 473 } 474 } 475 } 476 477 // wantArchive fails if path is not an archive. 478 func (t *T) wantArchive(path string) { 479 f, err := os.Open(path) 480 if err != nil { 481 t.Fatal(err) 482 } 483 buf := make([]byte, 100) 484 io.ReadFull(f, buf) 485 f.Close() 486 if !bytes.HasPrefix(buf, []byte("!<arch>\n")) { 487 t.Fatalf("file %s exists but is not an archive", path) 488 } 489 } 490 491 // isStale returns whether pkg is stale. 492 func (t *T) isStale(pkg string) bool { 493 t.run("list", "-f", "{{.Stale}}", pkg) 494 switch v := strings.TrimSpace(t.getStdout()); v { 495 case "true": 496 return true 497 case "false": 498 return false 499 default: 500 t.Fatalf("unexpected output checking staleness of package %v: %v", pkg, v) 501 panic("unreachable") 502 } 503 } 504 505 // wantStale fails with msg if pkg is not stale. 506 func (t *T) wantStale(pkg, msg string) { 507 if !t.isStale(pkg) { 508 t.Fatal(msg) 509 } 510 } 511 512 // wantNotStale fails with msg if pkg is stale. 513 func (t *T) wantNotStale(pkg, msg string) { 514 if t.isStale(pkg) { 515 t.Fatal(msg) 516 } 517 } 518 519 // cleanup cleans up a test that runs testgb. 520 func (t *T) cleanup() { 521 if t.wd != "" { 522 if err := os.Chdir(t.wd); err != nil { 523 // We are unlikely to be able to continue. 524 fmt.Fprintln(os.Stderr, "could not restore working directory, crashing:", err) 525 os.Exit(2) 526 } 527 } 528 for _, path := range t.temps { 529 t.check(os.RemoveAll(path)) 530 } 531 if t.tempdir != "" { 532 t.check(os.RemoveAll(t.tempdir)) 533 } 534 } 535 536 // resetReadOnlyFlagAll resets windows read-only flag 537 // set on path and any children it contains. 538 // The flag is set by git and has to be removed. 539 // os.Remove refuses to remove files with read-only flag set. 540 func (t *T) resetReadOnlyFlagAll(path string) { 541 fi, err := os.Stat(path) 542 if err != nil { 543 t.Fatalf("resetReadOnlyFlagAll(%q) failed: %v", path, err) 544 } 545 if !fi.IsDir() { 546 err := os.Chmod(path, 0666) 547 if err != nil { 548 t.Fatalf("resetReadOnlyFlagAll(%q) failed: %v", path, err) 549 } 550 } 551 fd, err := os.Open(path) 552 if err != nil { 553 t.Fatalf("resetReadOnlyFlagAll(%q) failed: %v", path, err) 554 } 555 defer fd.Close() 556 names, _ := fd.Readdirnames(-1) 557 for _, name := range names { 558 t.resetReadOnlyFlagAll(path + string(filepath.Separator) + name) 559 } 560 } 561 562 // Invoking plain "gb" should print usage to stderr and exit with 2. 563 func TestNoArguments(t *testing.T) { 564 gb := T{T: t} 565 defer gb.cleanup() 566 567 gb.tempDir("src") 568 gb.cd(gb.tempdir) 569 gb.runFail() 570 gb.grepStderr("^Usage:", `expected "Usage: ..."`) 571 } 572 573 // Invoking plain "gb" outside a project should print to stderr and exit with 2. 574 func TestOutsideProject(t *testing.T) { 575 gb := T{T: t} 576 defer gb.cleanup() 577 578 gb.tempDir("x") 579 gb.cd(gb.tempdir, "x") 580 gb.runFail() 581 gb.grepStderr("^Usage:", `expected "Usage: ..."`) 582 } 583 584 // Invoking gb outside a project should print to stderr and exit with 2. 585 func TestInfoOutsideProject(t *testing.T) { 586 gb := T{T: t} 587 defer gb.cleanup() 588 589 gb.tempDir("x") 590 gb.cd(gb.tempdir, "x") 591 gb.runFail("info") 592 regex := `FATAL: unable to construct context: could not locate project root: could not find project root in "` + 593 regexp.QuoteMeta(filepath.Join(gb.tempdir, "x")) + 594 `" or its parents` 595 gb.grepStderr(regex, "expected FATAL") 596 } 597 598 // Invoking gb outside a project with -R should succeed. 599 func TestInfoWithMinusR(t *testing.T) { 600 gb := T{T: t} 601 defer gb.cleanup() 602 603 gb.tempDir("x") 604 gb.tempDir("y") 605 gb.tempDir("y/src") 606 gb.cd(gb.tempdir, "x") 607 gb.run("info", "-R", filepath.Join(gb.tempdir, "y")) 608 gb.grepStdout(`^GB_PROJECT_DIR="`+regexp.QuoteMeta(filepath.Join(gb.tempdir, "y"))+`"$`, "missing GB_PROJECT_DIR") 609 } 610 611 func TestInfoCmd(t *testing.T) { 612 gb := T{T: t} 613 defer gb.cleanup() 614 615 gb.tempDir("src") 616 gb.cd(gb.tempdir) 617 gb.run("info") 618 gb.grepStdout(`^GB_PROJECT_DIR="`+regexp.QuoteMeta(gb.tempdir)+`"$`, "missing GB_PROJECT_DIR") 619 gb.grepStdout(`^GB_SRC_PATH="`+regexp.QuoteMeta(filepath.Join(gb.tempdir, "src")+string(filepath.ListSeparator)+filepath.Join(gb.tempdir, "vendor", "src"))+`"$`, "missing GB_SRC_PATH") 620 gb.grepStdout(`^GB_PKG_DIR="`+regexp.QuoteMeta(filepath.Join(gb.tempdir, "pkg", runtime.GOOS+"-"+runtime.GOARCH))+`"$`, "missing GB_PKG_DIR") 621 gb.grepStdout(`^GB_BIN_SUFFIX="-`+runtime.GOOS+"-"+runtime.GOARCH+`"$`, "missing GB_BIN_SUFFIX") 622 gb.grepStdout(`^GB_GOROOT="`+regexp.QuoteMeta(runtime.GOROOT())+`"$`, "missing GB_GOROOT") 623 } 624 625 func TestInfoWithArgs(t *testing.T) { 626 gb := T{T: t} 627 defer gb.cleanup() 628 629 gb.tempDir("src") 630 gb.cd(gb.tempdir) 631 gb.run("info", "GB_PROJECT_DIR", "GB_MISSING", "GB_GOROOT") 632 gb.grepStdout(`^`+regexp.QuoteMeta(gb.tempdir), "missing "+regexp.QuoteMeta(gb.tempdir)) 633 gb.grepStdout(`^`+regexp.QuoteMeta(runtime.GOROOT()), "missing "+regexp.QuoteMeta(runtime.GOROOT())) 634 // second line should be empty 635 lines := bytes.Split(gb.stdout.Bytes(), []byte{'\n'}) 636 if len(lines[1]) != 0 { 637 t.Fatal("want 0, got", len(lines[1])) 638 } 639 } 640 641 // Only succeeds if source order is preserved. 642 func TestSourceFileNameOrderPreserved(t *testing.T) { 643 gb := T{T: t} 644 defer gb.cleanup() 645 gb.tempDir("src") 646 gb.tempDir("src/testorder") 647 gb.tempFile("src/testorder/example1_test.go", `// Copyright 2013 The Go Authors. All rights reserved. 648 // Use of this source code is governed by a BSD-style 649 // license that can be found in the LICENSE file. 650 651 // Make sure that go test runs Example_Z before Example_A, preserving source order. 652 653 package p 654 655 import "fmt" 656 657 var n int 658 659 func Example_Z() { 660 n++ 661 fmt.Println(n) 662 // Output: 1 663 } 664 665 func Example_A() { 666 n++ 667 fmt.Println(n) 668 // Output: 2 669 } 670 `) 671 gb.tempFile("src/testorder/example2_test.go", `// Copyright 2013 The Go Authors. All rights reserved. 672 // Use of this source code is governed by a BSD-style 673 // license that can be found in the LICENSE file. 674 675 // Make sure that go test runs Example_Y before Example_B, preserving source order. 676 677 package p 678 679 import "fmt" 680 681 func Example_Y() { 682 n++ 683 fmt.Println(n) 684 // Output: 3 685 } 686 687 func Example_B() { 688 n++ 689 fmt.Println(n) 690 // Output: 4 691 } 692 `) 693 gb.cd(gb.tempdir) 694 gb.run("test", "testorder") 695 } 696 697 func TestBuildPackage(t *testing.T) { 698 gb := T{T: t} 699 defer gb.cleanup() 700 gb.tempDir("src") 701 gb.tempDir("src/pkg1") 702 gb.tempFile("src/pkg1/pkg.go", `package pkg1 703 import "fmt" 704 705 func helloworld() { 706 fmt.Println("hello world!") 707 } 708 `) 709 gb.cd(gb.tempdir) 710 tmpdir := gb.tempDir("tmp") 711 gb.setenv("TMP", tmpdir) 712 gb.run("build") 713 gb.grepStdout("^pkg1$", `expected "pkg1"`) 714 gb.mustBeEmpty(tmpdir) 715 gb.wantArchive(filepath.Join(gb.tempdir, "pkg", runtime.GOOS+"-"+runtime.GOARCH, "pkg1.a")) 716 } 717 718 func TestBuildOnlyOnePackage(t *testing.T) { 719 gb := T{T: t} 720 defer gb.cleanup() 721 gb.tempDir("src") 722 gb.tempDir("src/pkg1") 723 gb.tempFile("src/pkg1/pkg.go", `package pkg1 724 import "fmt" 725 726 func helloworld() { 727 fmt.Println("hello world!") 728 } 729 `) 730 gb.tempDir("src/pkg2") 731 gb.tempFile("src/pkg2/pkg.go", `package pkg2 732 import "fmt" 733 734 func helloworld() { 735 fmt.Println("hello world!") 736 } 737 `) 738 gb.cd(gb.tempdir) 739 tmpdir := gb.tempDir("tmp") 740 gb.setenv("TMP", tmpdir) 741 gb.run("build", "pkg1") 742 gb.grepStdout("^pkg1$", `expected "pkg1"`) 743 gb.grepStdoutNot("^pkg2$", `did not expect "pkg2"`) 744 gb.mustBeEmpty(tmpdir) 745 gb.wantArchive(filepath.Join(gb.tempdir, "pkg", runtime.GOOS+"-"+runtime.GOARCH, "pkg1.a")) 746 } 747 748 func TestBuildOnlyOnePackageFromWorkingDir(t *testing.T) { 749 gb := T{T: t} 750 defer gb.cleanup() 751 gb.tempDir("src") 752 gb.tempDir("src/pkg1") 753 gb.tempFile("src/pkg1/pkg.go", `package pkg1 754 import "fmt" 755 756 func helloworld() { 757 fmt.Println("hello world!") 758 } 759 `) 760 gb.tempDir("src/pkg2") 761 gb.tempFile("src/pkg2/pkg.go", `package pkg2 762 import "fmt" 763 764 func helloworld() { 765 fmt.Println("hello world!") 766 } 767 `) 768 gb.cd(filepath.Join(gb.tempdir, "src", "pkg1")) 769 tmpdir := gb.tempDir("tmp") 770 gb.setenv("TMP", tmpdir) 771 gb.run("build") 772 gb.grepStdout("^pkg1$", `expected "pkg1"`) 773 gb.grepStdoutNot("^pkg2$", `did not expect "pkg2"`) 774 gb.mustBeEmpty(tmpdir) 775 gb.wantArchive(filepath.Join(gb.tempdir, "pkg", runtime.GOOS+"-"+runtime.GOARCH, "pkg1.a")) 776 } 777 778 func TestBuildPackageWrongPackage(t *testing.T) { 779 gb := T{T: t} 780 defer gb.cleanup() 781 gb.tempDir("src") 782 gb.tempDir("src/pkg1") 783 gb.tempFile("src/pkg1/pkg.go", `package pkg1 784 import "fmt" 785 786 func helloworld() { 787 fmt.Println("hello world!") 788 } 789 `) 790 gb.cd(gb.tempdir) 791 gb.runFail("build", "pkg2") 792 gb.grepStderr(`^FATAL: command "build" failed: failed to resolve import path "pkg2": import "pkg2": not found`, "expected FATAL") 793 } 794 795 func TestBuildPackageNoSource(t *testing.T) { 796 gb := T{T: t} 797 defer gb.cleanup() 798 gb.tempDir("src") 799 gb.tempDir("src/pkg1") 800 gb.cd(gb.tempdir) 801 gb.runFail("build", "pkg1") 802 gb.grepStderr(`^FATAL: command "build" failed: failed to resolve import path "pkg1": no buildable Go source files in `+regexp.QuoteMeta(filepath.Join(gb.tempdir, "src", "pkg1")), "expected FATAL") 803 } 804 805 func TestTestPackageNoTests(t *testing.T) { 806 gb := T{T: t} 807 defer gb.cleanup() 808 gb.tempDir("src") 809 gb.tempDir("src/pkg1") 810 gb.tempFile("src/pkg1/pkg.go", `package pkg1 811 import "fmt" 812 813 func helloworld() { 814 fmt.Println("hello world!") 815 } 816 `) 817 gb.cd(gb.tempdir) 818 tmpdir := gb.tempDir("tmp") 819 gb.setenv("TMP", tmpdir) 820 gb.run("test", "pkg1") 821 gb.grepStdout("^pkg1$", `expected "pkg1"`) 822 gb.mustBeEmpty(tmpdir) 823 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 824 } 825 826 // test that compiling A in test scope compiles B in regular scope 827 func TestTestDepdenantPackage(t *testing.T) { 828 gb := T{T: t} 829 defer gb.cleanup() 830 gb.tempDir("src") 831 gb.tempDir("src/A") 832 gb.tempDir("src/B") 833 gb.tempFile("src/B/B.go", `package B 834 const X = 1 835 `) 836 gb.tempFile("src/A/A_test.go", `package A 837 import "testing" 838 import "B" 839 840 func TestX(t *testing.T) { 841 if B.X != 1 { 842 t.Fatal("expected 1, got %d", B.X) 843 } 844 } 845 `) 846 gb.cd(gb.tempdir) 847 tmpdir := gb.tempDir("tmp") 848 gb.setenv("TMP", tmpdir) 849 gb.run("test", "A") 850 gb.grepStdout("^B$", `expected "B"`) // output from build action 851 gb.grepStdout("^A$", `expected "A"`) // output from test action 852 gb.mustBeEmpty(tmpdir) 853 gb.wantArchive(filepath.Join(gb.tempdir, "pkg", runtime.GOOS+"-"+runtime.GOARCH, "B.a")) 854 } 855 856 func TestTestPackageOnlyTests(t *testing.T) { 857 gb := T{T: t} 858 defer gb.cleanup() 859 gb.tempDir("src") 860 gb.tempDir("src/pkg1") 861 gb.tempFile("src/pkg1/pkg_test.go", `package pkg1 862 import "testing" 863 864 func TestTest(t *testing.T) { 865 t.Log("hello") 866 } 867 `) 868 gb.cd(gb.tempdir) 869 tmpdir := gb.tempDir("tmp") 870 gb.setenv("TMP", tmpdir) 871 gb.run("test", "pkg1") 872 gb.grepStdout("^pkg1$", `expected "pkg1"`) 873 gb.mustBeEmpty(tmpdir) 874 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 875 } 876 877 func TestTestPackageFailedToBuild(t *testing.T) { 878 gb := T{T: t} 879 defer gb.cleanup() 880 gb.tempDir("src") 881 gb.tempDir("src/pkg1") 882 gb.tempFile("src/pkg1/pkg_test.go", `package pkg1 883 import "testing" 884 885 func TestTest(t *testing.T) { 886 t.Log("hello" // missing parens 887 } 888 `) 889 gb.cd(gb.tempdir) 890 tmpdir := gb.tempDir("tmp") 891 gb.setenv("TMP", tmpdir) 892 gb.runFail("test") 893 gb.grepStderr(`FATAL: command "test" failed:`, "expected FATAL") 894 gb.mustBeEmpty(tmpdir) 895 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 896 } 897 898 func TestTestPackageTestFailed(t *testing.T) { 899 gb := T{T: t} 900 defer gb.cleanup() 901 gb.tempDir("src") 902 gb.tempDir("src/pkg1") 903 gb.tempFile("src/pkg1/pkg_test.go", `package pkg1 904 import "testing" 905 906 func TestTest(t *testing.T) { 907 t.Error("failed") 908 } 909 `) 910 gb.cd(gb.tempdir) 911 tmpdir := gb.tempDir("tmp") 912 gb.setenv("TMP", tmpdir) 913 gb.runFail("test") 914 gb.grepStderr("^# pkg1$", "expected # pkg1") 915 gb.grepStdout("pkg_test.go:6: failed", "expected message from test") 916 gb.mustBeEmpty(tmpdir) 917 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 918 } 919 920 func TestTestPackageMinusV(t *testing.T) { 921 gb := T{T: t} 922 defer gb.cleanup() 923 gb.tempDir("src") 924 gb.tempDir("src/pkg1") 925 gb.tempFile("src/pkg1/pkg_test.go", `package pkg1 926 import "testing" 927 928 func TestTest(t *testing.T) { 929 t.Logf("hello") 930 } 931 `) 932 gb.cd(gb.tempdir) 933 tmpdir := gb.tempDir("tmp") 934 gb.setenv("TMP", tmpdir) 935 gb.run("test", "-v") 936 gb.grepStdout("^pkg1$", "expected pkg1") 937 gb.grepStdout("pkg_test.go:6: hello", "expected output from test binary") 938 gb.grepStdout("PASS", "expected PASS") 939 gb.mustBeEmpty(tmpdir) 940 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 941 } 942 943 const issue349 = `package main 944 945 import ( 946 "flag" 947 "testing" 948 ) 949 950 var name = flag.String("name", "nsf", "what is your name") 951 952 func TestX(t *testing.T) { 953 if *name != "jardin" { 954 t.Fatalf("got: '%s', expected: 'jardin'", *name) 955 } 956 } 957 ` 958 959 // https://github.com/constabulary/gb/issues/349 960 func TestTestGbTestPassesUnknownFlags(t *testing.T) { 961 gb := T{T: t} 962 defer gb.cleanup() 963 gb.tempDir("src") 964 gb.tempDir("src/projectx") 965 gb.tempFile("src/projectx/main_test.go", issue349) 966 gb.cd(gb.tempdir) 967 tmpdir := gb.tempDir("tmp") 968 gb.setenv("TMP", tmpdir) 969 gb.run("test", "-name=jardin") 970 gb.grepStdout("^projectx$", "expected projectx") // output from gb test 971 gb.mustBeEmpty(tmpdir) 972 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 973 } 974 975 const issue473 = `package main 976 977 import ( 978 "flag" 979 "testing" 980 ) 981 982 var name = flag.String("name", "nsf", "what is your name") 983 984 func TestX(t *testing.T) { 985 } 986 987 func TestY(t *testing.T) { 988 } 989 ` 990 991 // https://github.com/constabulary/gb/issues/473 992 func TestGbTestIssue473a(t *testing.T) { 993 gb := T{T: t} 994 defer gb.cleanup() 995 gb.tempDir("src") 996 gb.tempDir("src/projectx") 997 gb.tempFile("src/projectx/main_test.go", issue473) 998 gb.cd(gb.tempdir) 999 tmpdir := gb.tempDir("tmp") 1000 gb.setenv("TMP", tmpdir) 1001 gb.run("test", "-v", "projectx", "-run", "TestX") 1002 gb.grepStdout("^projectx$", "expected projectx") // output from gb test 1003 gb.grepStdout("TestX", "expected TestX") 1004 gb.grepStdoutNot("TestY", "expected TestY") 1005 gb.mustBeEmpty(tmpdir) 1006 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 1007 } 1008 1009 func TestGbTestIssue473b(t *testing.T) { 1010 gb := T{T: t} 1011 defer gb.cleanup() 1012 gb.tempDir("src") 1013 gb.tempDir("src/projectx") 1014 gb.tempFile("src/projectx/main_test.go", issue473) 1015 gb.cd(gb.tempdir) 1016 tmpdir := gb.tempDir("tmp") 1017 gb.setenv("TMP", tmpdir) 1018 gb.run("test", "-v", "-run", "TestX", "projectx") 1019 gb.grepStdout("^projectx$", "expected projectx") // output from gb test 1020 gb.grepStdout("TestX", "expected TestX") 1021 gb.grepStdoutNot("TestY", "expected TestY") 1022 gb.mustBeEmpty(tmpdir) 1023 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 1024 } 1025 1026 func TestGbTestIssue473c(t *testing.T) { 1027 gb := T{T: t} 1028 defer gb.cleanup() 1029 gb.tempDir("src") 1030 gb.tempDir("src/projectx") 1031 gb.tempFile("src/projectx/main_test.go", issue473) 1032 gb.cd(gb.tempdir) 1033 tmpdir := gb.tempDir("tmp") 1034 gb.setenv("TMP", tmpdir) 1035 gb.run("test", "-v", "projectx") 1036 gb.grepStdout("^projectx$", "expected projectx") // output from gb test 1037 gb.grepStdout("TestX", "expected TestX") 1038 gb.grepStdout("TestY", "expected TestY") 1039 gb.mustBeEmpty(tmpdir) 1040 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 1041 } 1042 1043 func TestGbTestIssue473d(t *testing.T) { 1044 gb := T{T: t} 1045 defer gb.cleanup() 1046 gb.tempDir("src") 1047 gb.tempDir("src/projectx") 1048 gb.tempFile("src/projectx/main_test.go", issue473) 1049 gb.cd(gb.tempdir) 1050 tmpdir := gb.tempDir("tmp") 1051 gb.setenv("TMP", tmpdir) 1052 gb.run("test", "projectx", "-v") 1053 gb.grepStdout("^projectx$", "expected projectx") // output from gb test 1054 gb.grepStdout("TestX", "expected TestX") 1055 gb.grepStdout("TestY", "expected TestY") 1056 gb.mustBeEmpty(tmpdir) 1057 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 1058 } 1059 1060 // gb list with an empty project succeeds and returns nothing. 1061 func TestGbListEmpty(t *testing.T) { 1062 gb := T{T: t} 1063 defer gb.cleanup() 1064 gb.tempDir("src") 1065 gb.cd(gb.tempdir) 1066 tmpdir := gb.tempDir("tmp") 1067 gb.setenv("TMP", tmpdir) 1068 gb.run("list") 1069 gb.grepStdoutNot(".", "expected no output") 1070 gb.grepStderrNot(".", "expected no output") 1071 gb.mustBeEmpty(tmpdir) 1072 } 1073 1074 // gb list with a project with source at the top level should return nothing. 1075 func TestGbListSrcTopLevel(t *testing.T) { 1076 gb := T{T: t} 1077 defer gb.cleanup() 1078 gb.tempDir("src") 1079 gb.tempFile("src/main.go", "package main; func main() { println() }") 1080 gb.cd(gb.tempdir) 1081 gb.run("list") 1082 gb.grepStdoutNot(".", "expected no output") 1083 gb.grepStderrNot(".", "expected no output") 1084 } 1085 1086 func TestGbListSrcCmd(t *testing.T) { 1087 gb := T{T: t} 1088 defer gb.cleanup() 1089 gb.tempDir("src") 1090 gb.tempDir("src/cmd") 1091 gb.tempFile("src/cmd/main.go", "package main; func main() { println() }") 1092 gb.cd(gb.tempdir) 1093 gb.run("list") 1094 gb.grepStdout("cmd", "expected cmd") 1095 } 1096 1097 func mklistfixture(gb *T) { 1098 gb.tempDir("src/p") 1099 gb.tempDir("src/q") 1100 gb.tempDir("src/r/s") 1101 gb.tempFile("src/p/p.go", "package p; const P = 'p'") 1102 gb.tempFile("src/q/q.go", "package p; const Q = 'q'") // package name differs from import path 1103 gb.tempFile("src/r/r.go", "package r; const R = 'r'") 1104 gb.tempFile("src/r/s/s.go", "package s; const S = 's'") 1105 } 1106 1107 // gb list with a few projects should show them all. 1108 func TestGbList(t *testing.T) { 1109 gb := T{T: t} 1110 defer gb.cleanup() 1111 mklistfixture(&gb) 1112 gb.cd(gb.tempdir) 1113 gb.run("list") 1114 gb.grepStdout("^p$", "expected 'p'") 1115 gb.grepStdout("^q$", "expected 'q'") 1116 gb.grepStdout("^r$", "expected 'r'") 1117 gb.grepStdout("^r/s$", "expected 'r/s'") 1118 } 1119 1120 func TestGbListPart(t *testing.T) { 1121 gb := T{T: t} 1122 defer gb.cleanup() 1123 mklistfixture(&gb) 1124 gb.cd(gb.tempdir) 1125 gb.run("list", "r/...", "q") 1126 gb.grepStdoutNot("^p$", "unexpected 'p'") 1127 gb.grepStdout("^q$", "expected 'q'") 1128 gb.grepStdout("^r$", "expected 'r'") 1129 gb.grepStdout("^r/s$", "expected 'r/s'") 1130 } 1131 1132 func TestGbListPackageNames(t *testing.T) { 1133 gb := T{T: t} 1134 defer gb.cleanup() 1135 mklistfixture(&gb) 1136 gb.cd(gb.tempdir) 1137 gb.run("list", "-f", "{{ .Name }}") 1138 gb.grepStdout("^p$", "expected 'p'") 1139 gb.grepStdoutNot("^q$", "unexpected 'q'") 1140 gb.grepStdout("^r$", "expected 'r'") 1141 gb.grepStdout("^s$", "expected 's'") 1142 } 1143 1144 func TestGbListFormatFromStdin(t *testing.T) { 1145 gb := T{T: t} 1146 defer gb.cleanup() 1147 mklistfixture(&gb) 1148 gb.cd(gb.tempdir) 1149 gb.stdin = strings.NewReader("{{ .Name }}") 1150 gb.run("list", "-s") 1151 gb.grepStdout("^p$", "expected 'p'") 1152 gb.grepStdoutNot("^q$", "unexpected 'q'") 1153 gb.grepStdout("^r$", "expected 'r'") 1154 gb.grepStdout("^s$", "expected 's'") 1155 } 1156 1157 // TODO(dfc) add tests for -json 1158 1159 func skipWindows(t *testing.T, msg string) { 1160 if runtime.GOOS == "windows" { 1161 t.Skip("test skipped on windows:", msg) 1162 } 1163 } 1164 1165 // issue 481: check that project detection works correctly 1166 // in the presence of symlinks above the project root. 1167 func TestProjectRootDetectionWorksWithParentSymlink(t *testing.T) { 1168 skipWindows(t, "no symlinks, lol") 1169 gb := T{T: t} 1170 defer gb.cleanup() 1171 1172 gb.tempDir("code/project") 1173 gb.tempDir("code/project/src/a") 1174 gb.tempFile("code/project/src/a/a.go", "package a; const A = 'a'") 1175 root := gb.symlink("code", "code1") 1176 gb.cd(filepath.Join(root, "project")) 1177 gb.run("list") 1178 gb.grepStdout("^a$", "expected 'a'") 1179 } 1180 1181 func TestProjectRootDetectionWorksWithDirectSymlink(t *testing.T) { 1182 skipWindows(t, "no symlinks, lol") 1183 gb := T{T: t} 1184 defer gb.cleanup() 1185 1186 gb.tempDir("code/project") 1187 gb.tempDir("code/project/src/a") 1188 gb.tempFile("code/project/src/a/a.go", "package a; const A = 'a'") 1189 root := gb.symlink("code/project", "code/symlink") 1190 gb.cd(root) 1191 gb.run("list") 1192 gb.grepStdout("^a$", "expected 'a'") 1193 } 1194 1195 // issue 157 1196 func TestTestWorksWithProjectSymlink(t *testing.T) { 1197 skipWindows(t, "no symlinks, lol") 1198 gb := T{T: t} 1199 defer gb.cleanup() 1200 1201 gb.tempDir("code/project") 1202 gb.tempDir("code/project/src/a") 1203 gb.tempFile("code/project/src/a/a.go", "package a; const A = 'a'") 1204 gb.tempFile("code/project/src/a/a_test.go", `package a 1205 1206 import "testing" 1207 1208 func TestA(t *testing.T) { 1209 if A != 'a' { 1210 t.Fatal("expected a, got", A) 1211 } 1212 } 1213 `) 1214 root := gb.symlink("code/project", "code/symlink") 1215 gb.cd(root) 1216 gb.run("test") 1217 gb.grepStdout("^a$", "expected 'a'") 1218 } 1219 1220 func TestTestWorksInsideProjectSymlink(t *testing.T) { 1221 skipWindows(t, "no symlinks, lol") 1222 gb := T{T: t} 1223 defer gb.cleanup() 1224 1225 gb.tempDir("code/project") 1226 gb.tempDir("code/project/src/a") 1227 gb.tempFile("code/project/src/a/a.go", "package a; const A = 'a'") 1228 gb.tempFile("code/project/src/a/a_test.go", `package a 1229 1230 import "testing" 1231 1232 func TestA(t *testing.T) { 1233 if A != 'a' { 1234 t.Fatal("expected a, got", A) 1235 } 1236 } 1237 `) 1238 root := gb.symlink("code/project", "code/symlink") 1239 gb.cd(filepath.Join(root, "src", "a")) 1240 gb.run("test") 1241 gb.grepStdout("^a$", "expected 'a'") 1242 } 1243 1244 // test -race flag is wired up correctly 1245 func TestBuildRaceFlag(t *testing.T) { 1246 if !canRace { 1247 t.Skip("skipping because race detector not supported") 1248 } 1249 1250 gb := T{T: t} 1251 defer gb.cleanup() 1252 1253 gb.tempDir("src/x") 1254 gb.tempFile("src/x/x_race.go", "package x\nconst A = 1\n") 1255 gb.tempFile("src/x/y.go", "// +build race\n\npackage x\nconst B = 2\n") 1256 gb.tempFile("src/x/z.go", "package x\n const C = A +B\n") 1257 gb.cd(gb.tempdir) 1258 tmpdir := gb.tempDir("tmp") 1259 gb.setenv("TMP", tmpdir) 1260 gb.run("build", "-race", "x") 1261 gb.mustBeEmpty(tmpdir) 1262 gb.wantArchive(filepath.Join(gb.tempdir, "pkg", runtime.GOOS+"-"+runtime.GOARCH+"-race", "x.a")) 1263 } 1264 1265 func TestTestRaceFlag(t *testing.T) { 1266 if !canRace { 1267 t.Skip("skipping because race detector not supported") 1268 } 1269 1270 gb := T{T: t} 1271 defer gb.cleanup() 1272 1273 gb.tempDir("src/x") 1274 gb.tempFile("src/x/x_race.go", "package x\nconst A = 1\n") 1275 gb.tempFile("src/x/y.go", "// +build race\n\npackage x\nconst B = 2\n") 1276 gb.tempFile("src/x/q.go", "// +build !race\n\npackage x\nconst B = 7\n") 1277 gb.tempFile("src/x/x_test.go", `package x 1278 import "testing" 1279 1280 func TestRaceFlag(t *testing.T) { 1281 if A != 1 || B != 2 { 1282 t.Fatal("expected", 1, 2,"got", A, B) 1283 } 1284 } 1285 `) 1286 gb.cd(gb.tempdir) 1287 tmpdir := gb.tempDir("tmp") 1288 gb.setenv("TMP", tmpdir) 1289 gb.run("test", "-race", "x") 1290 gb.grepStdout("^x$", "expected x") // output from gb test 1291 gb.mustBeEmpty(tmpdir) 1292 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 1293 } 1294 1295 // check that go test -race builds and runs a racy binary, and that it finds the race. 1296 func TestTestRace(t *testing.T) { 1297 if !canRace { 1298 t.Skip("skipping because race detector not supported") 1299 } 1300 if strings.HasPrefix(runtime.Version(), "go1.4") { 1301 t.Skipf("skipping race test as Go version %v incorrectly marks race failures as success", runtime.Version()) 1302 } 1303 1304 gb := T{T: t} 1305 defer gb.cleanup() 1306 1307 gb.tempDir("src/race") 1308 gb.tempFile("src/race/map_test.go", `package race 1309 import "testing" 1310 1311 func TestRaceMapRW(t *testing.T) { 1312 m := make(map[int]int) 1313 ch := make(chan bool, 1) 1314 go func() { 1315 _ = m[1] 1316 ch <- true 1317 }() 1318 m[1] = 1 1319 <-ch 1320 } 1321 `) 1322 gb.cd(gb.tempdir) 1323 tmpdir := gb.tempDir("tmp") 1324 gb.setenv("TMP", tmpdir) 1325 gb.runFail("test", "-race") 1326 gb.mustBeEmpty(tmpdir) 1327 } 1328 1329 // check that missing -race support generates error message. 1330 func TestRaceMissing(t *testing.T) { 1331 if canRace { 1332 t.Skip("skipping because race detector is available") 1333 } 1334 1335 gb := T{T: t} 1336 defer gb.cleanup() 1337 1338 gb.tempDir("src/race") 1339 gb.tempFile("src/race/map_test.go", `package race 1340 import "testing" 1341 1342 func TestRaceMapRW(t *testing.T) { 1343 m := make(map[int]int) 1344 ch := make(chan bool, 1) 1345 go func() { 1346 _ = m[1] 1347 ch <- true 1348 }() 1349 m[1] = 1 1350 <-ch 1351 } 1352 `) 1353 gb.cd(gb.tempdir) 1354 tmpdir := gb.tempDir("tmp") 1355 gb.setenv("TMP", tmpdir) 1356 gb.runFail("test", "-race") 1357 gb.grepStderr(regexp.QuoteMeta(fmt.Sprintf("FATAL: go installation at %s is missing race support", runtime.GOROOT())), "expected missing race support message") 1358 gb.mustBeEmpty(tmpdir) 1359 } 1360 1361 // test that gb will no build the stdlib directly, only as transitive deps. 1362 func TestNoBuildStdlib(t *testing.T) { 1363 t.Skip("constabulary/gb#505") 1364 gb := T{T: t} 1365 defer gb.cleanup() 1366 gb.tempDir("src/") 1367 gb.cd(gb.tempdir) 1368 defer gb.cleanup() 1369 gb.runFail("build", "-f", "-F", "net/http") 1370 } 1371 1372 func TestCrossCompile(t *testing.T) { 1373 if strings.HasPrefix(runtime.Version(), "go1.4") { 1374 t.Skip("skipping cross compile test, not supported on", runtime.Version()) 1375 } 1376 gb := T{T: t} 1377 defer gb.cleanup() 1378 gb.tempDir("src/p") 1379 gb.tempFile("src/p/main.go", `package main 1380 func main() { println("hello world") } 1381 `) 1382 gb.cd(gb.tempdir) 1383 tmpdir := gb.tempDir("tmp") 1384 goos := "windows" 1385 if runtime.GOOS == goos { 1386 goos = "linux" 1387 } 1388 goarch := "386" 1389 if runtime.GOARCH == goarch { 1390 goarch = "amd64" 1391 } 1392 gb.setenv("TMP", tmpdir) 1393 gb.setenv("GOOS", goos) 1394 gb.setenv("GOARCH", goarch) 1395 gb.run("build") 1396 gb.mustBeEmpty(tmpdir) 1397 name := fmt.Sprintf("p-%s-%s", goos, goarch) 1398 if goos == "windows" { 1399 name += ".exe" 1400 } 1401 gb.mustExist(gb.path("bin", name)) 1402 gb.wantExecutable(gb.path("bin", name), "expected $PROJECT/bin/p-$GOOS-$GOARCH") 1403 } 1404 1405 // https://github.com/constabulary/gb/issues/416 1406 func TestGbBuildBuildsPackgeCalledCmd(t *testing.T) { 1407 gb := T{T: t} 1408 defer gb.cleanup() 1409 gb.tempDir("src/cmd") 1410 gb.tempFile("src/cmd/main.go", `package main 1411 func main() { println("hello world") } 1412 `) 1413 gb.cd(gb.tempdir) 1414 tmpdir := gb.tempDir("tmp") 1415 gb.setenv("TMP", tmpdir) 1416 gb.run("build") 1417 gb.mustBeEmpty(tmpdir) 1418 gb.grepStdout("^cmd$", "expected cmd") 1419 name := "cmd" 1420 if runtime.GOOS == "windows" { 1421 name += ".exe" 1422 } 1423 gb.mustExist(gb.path("bin", name)) 1424 gb.wantExecutable(gb.path("bin", name), "expected $PROJECT/bin/"+name) 1425 } 1426 1427 // https://github.com/constabulary/gb/issues/492 1428 func TestGbBuildSubPackageOfCmd(t *testing.T) { 1429 gb := T{T: t} 1430 defer gb.cleanup() 1431 gb.tempDir("src/cmd/hello") 1432 gb.tempFile("src/cmd/hello/main.go", `package main 1433 func main() { println("hello world") } 1434 `) 1435 gb.cd(gb.tempdir) 1436 tmpdir := gb.tempDir("tmp") 1437 gb.setenv("TMP", tmpdir) 1438 gb.run("build") 1439 gb.mustBeEmpty(tmpdir) 1440 name := "hello" 1441 if runtime.GOOS == "windows" { 1442 name += ".exe" 1443 } 1444 gb.wantExecutable(gb.path("bin", name), "expected $PROJECT/bin/hello") 1445 } 1446 1447 // https://github.com/constabulary/gb/issues/515 1448 func TestIssue515(t *testing.T) { 1449 gb := T{T: t} 1450 defer gb.cleanup() 1451 gb.tempDir("src/main") 1452 gb.tempFile("src/main/main.go", `package main 1453 1454 import ( 1455 "log" 1456 "net/http" 1457 ) 1458 1459 func main() { 1460 err := http.ListenAndServe(":8080", nil) 1461 if err != nil { 1462 log.Fatal("ListenAndServe: ", err) 1463 } else { 1464 log.Print("Server started!") 1465 } 1466 } 1467 `) 1468 gb.cd(gb.tempdir) 1469 tmpdir := gb.tempDir("tmp") 1470 gb.setenv("TMP", tmpdir) 1471 gb.run("build") 1472 gb.mustBeEmpty(tmpdir) 1473 name := "main" 1474 if runtime.GOOS == "windows" { 1475 name += ".exe" 1476 } 1477 gb.wantExecutable(gb.path("bin", name), "expected $PROJECT/bin/main") 1478 } 1479 1480 func TestGbGenerate(t *testing.T) { 1481 if runtime.GOOS == "windows" { 1482 t.Skipf("windows doesn't have echo, lol") 1483 } 1484 gb := T{T: t} 1485 defer gb.cleanup() 1486 gb.tempDir("src/gentest") 1487 gb.tempFile("src/gentest/generate.go", `package gentest 1488 //go:generate echo $GOPACKAGE $GOFILE 1489 `) 1490 gb.cd(gb.tempdir) 1491 gb.run("generate") 1492 gb.grepStdout("^gentest generate.go$", "expected $GOPACKAGE $GOFILE") 1493 } 1494 1495 func TestGbDoc(t *testing.T) { 1496 if runtime.GOOS == "windows" { 1497 t.Skipf("windows doesn't have echo, lol") 1498 } 1499 gb := T{T: t} 1500 defer gb.cleanup() 1501 gb.tempDir("src/doctest") 1502 gb.tempFile("src/doctest/doc.go", `// Package doctest tests gb doc 1503 package doctest 1504 `) 1505 gb.cd(gb.tempdir) 1506 gb.run("doc", "doctest") 1507 gb.grepStdout("Package doctest tests gb doc$", "expected Package doctest tests gb doc") 1508 } 1509 1510 func TestIssue346(t *testing.T) { 1511 gb := T{T: t} 1512 defer gb.cleanup() 1513 gb.tempDir("src/p") 1514 gb.tempFile("src/p/main.go", `package main 1515 func main() { println("hello world") } 1516 `) 1517 gb.cd(gb.tempdir) 1518 tmpdir := gb.tempDir("tmp") 1519 gb.setenv("TMP", tmpdir) 1520 1521 goos := runtime.GOOS 1522 1523 // scenario 1: GOOS/GOARCH not set 1524 name := "p" 1525 if goos == "windows" { 1526 name += ".exe" 1527 } 1528 gb.unsetenv("GOOS") 1529 gb.unsetenv("GOARCH") 1530 gb.run("build") 1531 gb.wantExecutable(gb.path("bin", name), "expected $PROJECT/bin/p") 1532 1533 // scenario 2: GOOS/GOARCH are both set 1534 name = fmt.Sprintf("p-%s-%s", goos, runtime.GOARCH) 1535 if goos == "windows" { 1536 name += ".exe" 1537 } 1538 gb.setenv("GOOS", goos) 1539 gb.setenv("GOARCH", runtime.GOARCH) 1540 gb.run("build") 1541 gb.wantExecutable(gb.path("bin", name), "expected $PROJECT/bin/p-$GOOS-$GOARCH") 1542 1543 // scenario 3: just GOOS is set 1544 os.Remove(gb.path("bin", name)) 1545 gb.unsetenv("GOARCH") 1546 gb.run("build") 1547 gb.mustNotExist(gb.path("bin", name)) 1548 } 1549 1550 func TestGbBuildCannotReferencePackagesInGoroot(t *testing.T) { 1551 gb := T{T: t} 1552 defer gb.cleanup() 1553 1554 gb.tempDir("src") 1555 gb.cd(gb.tempdir) 1556 tmpdir := gb.tempDir("tmp") 1557 1558 gb.setenv("TMP", tmpdir) 1559 gb.runFail("build", "net/http") // net/http will be excluded by resolveRootPackages 1560 gb.mustBeEmpty(tmpdir) 1561 gb.mustNotExist(gb.path("pkg")) 1562 gb.grepStderr(`FATAL: command "build" failed: no packages supplied`, "expected FATAL") 1563 } 1564 1565 func TestGbBuildWillResolvePackagesInVendorAsRoots(t *testing.T) { 1566 gb := T{T: t} 1567 defer gb.cleanup() 1568 1569 gb.tempDir("src") 1570 gb.tempDir("vendor/src/test/test1") 1571 gb.tempFile("vendor/src/test/test1/test1.go", `package http 1572 func init() { 1573 println("Hello, world!") 1574 } 1575 `) 1576 gb.cd(gb.tempdir) 1577 tmpdir := gb.tempDir("tmp") 1578 1579 gb.setenv("TMP", tmpdir) 1580 gb.runFail("build") // should fail, nothing supplied 1581 gb.mustBeEmpty(tmpdir) 1582 gb.mustNotExist(gb.path("pkg")) 1583 gb.grepStderr(`FATAL: command "build" failed: no packages supplied`, "expected FATAL") 1584 1585 gb.runFail("build", "test/...") // should fail, globbing does not match $PROJECT/vendor/src 1586 gb.mustBeEmpty(tmpdir) 1587 gb.mustNotExist(gb.path("pkg")) 1588 gb.grepStderr(`FATAL: command "build" failed: no packages supplied`, "expected FATAL") 1589 1590 gb.run("build", "test/test1") // should resolve to vendor/src/test/test1 1591 gb.mustBeEmpty(tmpdir) 1592 gb.wantArchive(filepath.Join(gb.tempdir, "pkg", runtime.GOOS+"-"+runtime.GOARCH, "test", "test1.a")) 1593 gb.grepStdout(`^test/test`, "expected test/test1") 1594 } 1595 1596 func TestIssue550(t *testing.T) { 1597 gb := T{T: t} 1598 defer gb.cleanup() 1599 1600 gb.tempDir("src/x") 1601 gb.tempFile("src/x/x.go", `package main 1602 1603 import ( 1604 "log" 1605 "this/is/a/bad/path" 1606 ) 1607 1608 func main() { 1609 log.Println("Hello World.") 1610 } 1611 `) 1612 gb.cd(gb.tempdir) 1613 tmpdir := gb.tempDir("tmp") 1614 1615 gb.setenv("TMP", tmpdir) 1616 name := "x" 1617 if runtime.GOOS == "windows" { 1618 name += ".exe" 1619 } 1620 gb.runFail("build") 1621 gb.mustBeEmpty(tmpdir) 1622 gb.grepStderr(`FATAL: command "build" failed: failed to resolve import path "x": import "this/is/a/bad/path": not found`, "expected FATAL") 1623 }