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