github.com/aca02djr/gb@v0.4.1/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: failed to resolve import path "pkg1": no buildable Go source files in `+regexp.QuoteMeta(filepath.Join(gb.tempdir, "src", "pkg1")), "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 TestTestDepdenantPackage(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 TestTestPackageFailedToBuild(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" // missing parens 884 } 885 `) 886 gb.cd(gb.tempdir) 887 tmpdir := gb.tempDir("tmp") 888 gb.setenv("TMP", tmpdir) 889 gb.runFail("test") 890 gb.grepStderr(`FATAL: command "test" failed:`, "expected FATAL") 891 gb.mustBeEmpty(tmpdir) 892 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 893 } 894 895 func TestTestPackageTestFailed(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.Error("failed") 905 } 906 `) 907 gb.cd(gb.tempdir) 908 tmpdir := gb.tempDir("tmp") 909 gb.setenv("TMP", tmpdir) 910 gb.runFail("test") 911 gb.grepStderr("^# pkg1$", "expected # pkg1") 912 gb.grepStdout("pkg_test.go:6: failed", "expected message from test") 913 gb.mustBeEmpty(tmpdir) 914 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 915 } 916 917 func TestTestPackageMinusV(t *testing.T) { 918 gb := T{T: t} 919 defer gb.cleanup() 920 gb.tempDir("src") 921 gb.tempDir("src/pkg1") 922 gb.tempFile("src/pkg1/pkg_test.go", `package pkg1 923 import "testing" 924 925 func TestTest(t *testing.T) { 926 t.Logf("hello") 927 } 928 `) 929 gb.cd(gb.tempdir) 930 tmpdir := gb.tempDir("tmp") 931 gb.setenv("TMP", tmpdir) 932 gb.run("test", "-v") 933 gb.grepStdout("^pkg1$", "expected pkg1") 934 gb.grepStdout("pkg_test.go:6: hello", "expected output from test binary") 935 gb.grepStdout("PASS", "expected PASS") 936 gb.mustBeEmpty(tmpdir) 937 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 938 } 939 940 const issue349 = `package main 941 942 import ( 943 "flag" 944 "testing" 945 ) 946 947 var name = flag.String("name", "nsf", "what is your name") 948 949 func TestX(t *testing.T) { 950 if *name != "jardin" { 951 t.Fatalf("got: '%s', expected: 'jardin'", *name) 952 } 953 } 954 ` 955 956 // https://github.com/constabulary/gb/issues/349 957 func TestTestGbTestPassesUnknownFlags(t *testing.T) { 958 gb := T{T: t} 959 defer gb.cleanup() 960 gb.tempDir("src") 961 gb.tempDir("src/projectx") 962 gb.tempFile("src/projectx/main_test.go", issue349) 963 gb.cd(gb.tempdir) 964 tmpdir := gb.tempDir("tmp") 965 gb.setenv("TMP", tmpdir) 966 gb.run("test", "-name=jardin") 967 gb.grepStdout("^projectx$", "expected projectx") // output from gb test 968 gb.mustBeEmpty(tmpdir) 969 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 970 } 971 972 const issue473 = `package main 973 974 import ( 975 "flag" 976 "testing" 977 ) 978 979 var name = flag.String("name", "nsf", "what is your name") 980 981 func TestX(t *testing.T) { 982 } 983 984 func TestY(t *testing.T) { 985 } 986 ` 987 988 // https://github.com/constabulary/gb/issues/473 989 func TestGbTestIssue473a(t *testing.T) { 990 gb := T{T: t} 991 defer gb.cleanup() 992 gb.tempDir("src") 993 gb.tempDir("src/projectx") 994 gb.tempFile("src/projectx/main_test.go", issue473) 995 gb.cd(gb.tempdir) 996 tmpdir := gb.tempDir("tmp") 997 gb.setenv("TMP", tmpdir) 998 gb.run("test", "-v", "projectx", "-run", "TestX") 999 gb.grepStdout("^projectx$", "expected projectx") // output from gb test 1000 gb.grepStdout("TestX", "expected TestX") 1001 gb.grepStdoutNot("TestY", "expected TestY") 1002 gb.mustBeEmpty(tmpdir) 1003 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 1004 } 1005 1006 func TestGbTestIssue473b(t *testing.T) { 1007 gb := T{T: t} 1008 defer gb.cleanup() 1009 gb.tempDir("src") 1010 gb.tempDir("src/projectx") 1011 gb.tempFile("src/projectx/main_test.go", issue473) 1012 gb.cd(gb.tempdir) 1013 tmpdir := gb.tempDir("tmp") 1014 gb.setenv("TMP", tmpdir) 1015 gb.run("test", "-v", "-run", "TestX", "projectx") 1016 gb.grepStdout("^projectx$", "expected projectx") // output from gb test 1017 gb.grepStdout("TestX", "expected TestX") 1018 gb.grepStdoutNot("TestY", "expected TestY") 1019 gb.mustBeEmpty(tmpdir) 1020 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 1021 } 1022 1023 func TestGbTestIssue473c(t *testing.T) { 1024 gb := T{T: t} 1025 defer gb.cleanup() 1026 gb.tempDir("src") 1027 gb.tempDir("src/projectx") 1028 gb.tempFile("src/projectx/main_test.go", issue473) 1029 gb.cd(gb.tempdir) 1030 tmpdir := gb.tempDir("tmp") 1031 gb.setenv("TMP", tmpdir) 1032 gb.run("test", "-v", "projectx") 1033 gb.grepStdout("^projectx$", "expected projectx") // output from gb test 1034 gb.grepStdout("TestX", "expected TestX") 1035 gb.grepStdout("TestY", "expected TestY") 1036 gb.mustBeEmpty(tmpdir) 1037 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 1038 } 1039 1040 func TestGbTestIssue473d(t *testing.T) { 1041 gb := T{T: t} 1042 defer gb.cleanup() 1043 gb.tempDir("src") 1044 gb.tempDir("src/projectx") 1045 gb.tempFile("src/projectx/main_test.go", issue473) 1046 gb.cd(gb.tempdir) 1047 tmpdir := gb.tempDir("tmp") 1048 gb.setenv("TMP", tmpdir) 1049 gb.run("test", "projectx", "-v") 1050 gb.grepStdout("^projectx$", "expected projectx") // output from gb test 1051 gb.grepStdout("TestX", "expected TestX") 1052 gb.grepStdout("TestY", "expected TestY") 1053 gb.mustBeEmpty(tmpdir) 1054 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 1055 } 1056 1057 // gb list with an empty project succeeds and returns nothing. 1058 func TestGbListEmpty(t *testing.T) { 1059 gb := T{T: t} 1060 defer gb.cleanup() 1061 gb.tempDir("src") 1062 gb.cd(gb.tempdir) 1063 tmpdir := gb.tempDir("tmp") 1064 gb.setenv("TMP", tmpdir) 1065 gb.run("list") 1066 gb.grepStdoutNot(".", "expected no output") 1067 gb.grepStderrNot(".", "expected no output") 1068 gb.mustBeEmpty(tmpdir) 1069 } 1070 1071 // gb list with a project with source at the top level should return nothing. 1072 func TestGbListSrcTopLevel(t *testing.T) { 1073 gb := T{T: t} 1074 defer gb.cleanup() 1075 gb.tempDir("src") 1076 gb.tempFile("src/main.go", "package main; func main() { println() }") 1077 gb.cd(gb.tempdir) 1078 gb.run("list") 1079 gb.grepStdoutNot(".", "expected no output") 1080 gb.grepStderrNot(".", "expected no output") 1081 } 1082 1083 func TestGbListSrcCmd(t *testing.T) { 1084 gb := T{T: t} 1085 defer gb.cleanup() 1086 gb.tempDir("src") 1087 gb.tempDir("src/cmd") 1088 gb.tempFile("src/cmd/main.go", "package main; func main() { println() }") 1089 gb.cd(gb.tempdir) 1090 gb.run("list") 1091 gb.grepStdout("cmd", "expected cmd") 1092 } 1093 1094 func mklistfixture(gb *T) { 1095 gb.tempDir("src/p") 1096 gb.tempDir("src/q") 1097 gb.tempDir("src/r/s") 1098 gb.tempFile("src/p/p.go", "package p; const P = 'p'") 1099 gb.tempFile("src/q/q.go", "package p; const Q = 'q'") // package name differs from import path 1100 gb.tempFile("src/r/r.go", "package r; const R = 'r'") 1101 gb.tempFile("src/r/s/s.go", "package s; const S = 's'") 1102 } 1103 1104 // gb list with a few projects should show them all. 1105 func TestGbList(t *testing.T) { 1106 gb := T{T: t} 1107 defer gb.cleanup() 1108 mklistfixture(&gb) 1109 gb.cd(gb.tempdir) 1110 gb.run("list") 1111 gb.grepStdout("^p$", "expected 'p'") 1112 gb.grepStdout("^q$", "expected 'q'") 1113 gb.grepStdout("^r$", "expected 'r'") 1114 gb.grepStdout("^r/s$", "expected 'r/s'") 1115 } 1116 1117 func TestGbListPart(t *testing.T) { 1118 gb := T{T: t} 1119 defer gb.cleanup() 1120 mklistfixture(&gb) 1121 gb.cd(gb.tempdir) 1122 gb.run("list", "r/...", "q") 1123 gb.grepStdoutNot("^p$", "unexpected 'p'") 1124 gb.grepStdout("^q$", "expected 'q'") 1125 gb.grepStdout("^r$", "expected 'r'") 1126 gb.grepStdout("^r/s$", "expected 'r/s'") 1127 } 1128 1129 func TestGbListPackageNames(t *testing.T) { 1130 gb := T{T: t} 1131 defer gb.cleanup() 1132 mklistfixture(&gb) 1133 gb.cd(gb.tempdir) 1134 gb.run("list", "-f", "{{ .Name }}") 1135 gb.grepStdout("^p$", "expected 'p'") 1136 gb.grepStdoutNot("^q$", "unexpected 'q'") 1137 gb.grepStdout("^r$", "expected 'r'") 1138 gb.grepStdout("^s$", "expected 's'") 1139 } 1140 1141 func TestGbListFormatFromStdin(t *testing.T) { 1142 gb := T{T: t} 1143 defer gb.cleanup() 1144 mklistfixture(&gb) 1145 gb.cd(gb.tempdir) 1146 gb.stdin = strings.NewReader("{{ .Name }}") 1147 gb.run("list", "-s") 1148 gb.grepStdout("^p$", "expected 'p'") 1149 gb.grepStdoutNot("^q$", "unexpected 'q'") 1150 gb.grepStdout("^r$", "expected 'r'") 1151 gb.grepStdout("^s$", "expected 's'") 1152 } 1153 1154 // TODO(dfc) add tests for -json 1155 1156 func skipWindows(t *testing.T, msg string) { 1157 if runtime.GOOS == "windows" { 1158 t.Skip("test skipped on windows:", msg) 1159 } 1160 } 1161 1162 // issue 481: check that project detection works correctly 1163 // in the presence of symlinks above the project root. 1164 func TestProjectRootDetectionWorksWithParentSymlink(t *testing.T) { 1165 skipWindows(t, "no symlinks, lol") 1166 gb := T{T: t} 1167 defer gb.cleanup() 1168 1169 gb.tempDir("code/project") 1170 gb.tempDir("code/project/src/a") 1171 gb.tempFile("code/project/src/a/a.go", "package a; const A = 'a'") 1172 root := gb.symlink("code", "code1") 1173 gb.cd(filepath.Join(root, "project")) 1174 gb.run("list") 1175 gb.grepStdout("^a$", "expected 'a'") 1176 } 1177 1178 func TestProjectRootDetectionWorksWithDirectSymlink(t *testing.T) { 1179 skipWindows(t, "no symlinks, lol") 1180 gb := T{T: t} 1181 defer gb.cleanup() 1182 1183 gb.tempDir("code/project") 1184 gb.tempDir("code/project/src/a") 1185 gb.tempFile("code/project/src/a/a.go", "package a; const A = 'a'") 1186 root := gb.symlink("code/project", "code/symlink") 1187 gb.cd(root) 1188 gb.run("list") 1189 gb.grepStdout("^a$", "expected 'a'") 1190 } 1191 1192 // issue 157 1193 func TestTestWorksWithProjectSymlink(t *testing.T) { 1194 skipWindows(t, "no symlinks, lol") 1195 gb := T{T: t} 1196 defer gb.cleanup() 1197 1198 gb.tempDir("code/project") 1199 gb.tempDir("code/project/src/a") 1200 gb.tempFile("code/project/src/a/a.go", "package a; const A = 'a'") 1201 gb.tempFile("code/project/src/a/a_test.go", `package a 1202 1203 import "testing" 1204 1205 func TestA(t *testing.T) { 1206 if A != 'a' { 1207 t.Fatal("expected a, got", A) 1208 } 1209 } 1210 `) 1211 root := gb.symlink("code/project", "code/symlink") 1212 gb.cd(root) 1213 gb.run("test") 1214 gb.grepStdout("^a$", "expected 'a'") 1215 } 1216 1217 func TestTestWorksInsideProjectSymlink(t *testing.T) { 1218 skipWindows(t, "no symlinks, lol") 1219 gb := T{T: t} 1220 defer gb.cleanup() 1221 1222 gb.tempDir("code/project") 1223 gb.tempDir("code/project/src/a") 1224 gb.tempFile("code/project/src/a/a.go", "package a; const A = 'a'") 1225 gb.tempFile("code/project/src/a/a_test.go", `package a 1226 1227 import "testing" 1228 1229 func TestA(t *testing.T) { 1230 if A != 'a' { 1231 t.Fatal("expected a, got", A) 1232 } 1233 } 1234 `) 1235 root := gb.symlink("code/project", "code/symlink") 1236 gb.cd(filepath.Join(root, "src", "a")) 1237 gb.run("test") 1238 gb.grepStdout("^a$", "expected 'a'") 1239 } 1240 1241 // test -race flag is wired up correctly 1242 func TestBuildRaceFlag(t *testing.T) { 1243 if !canRace { 1244 t.Skip("skipping because race detector not supported") 1245 } 1246 1247 gb := T{T: t} 1248 defer gb.cleanup() 1249 1250 gb.tempDir("src/x") 1251 gb.tempFile("src/x/x_race.go", "package x\nconst A = 1\n") 1252 gb.tempFile("src/x/y.go", "// +build race\n\npackage x\nconst B = 2\n") 1253 gb.tempFile("src/x/z.go", "package x\n const C = A +B\n") 1254 gb.cd(gb.tempdir) 1255 tmpdir := gb.tempDir("tmp") 1256 gb.setenv("TMP", tmpdir) 1257 gb.run("build", "-race", "x") 1258 gb.mustBeEmpty(tmpdir) 1259 gb.wantArchive(filepath.Join(gb.tempdir, "pkg", runtime.GOOS+"-"+runtime.GOARCH+"-race", "x.a")) 1260 } 1261 1262 func TestTestRaceFlag(t *testing.T) { 1263 if !canRace { 1264 t.Skip("skipping because race detector not supported") 1265 } 1266 1267 gb := T{T: t} 1268 defer gb.cleanup() 1269 1270 gb.tempDir("src/x") 1271 gb.tempFile("src/x/x_race.go", "package x\nconst A = 1\n") 1272 gb.tempFile("src/x/y.go", "// +build race\n\npackage x\nconst B = 2\n") 1273 gb.tempFile("src/x/q.go", "// +build !race\n\npackage x\nconst B = 7\n") 1274 gb.tempFile("src/x/x_test.go", `package x 1275 import "testing" 1276 1277 func TestRaceFlag(t *testing.T) { 1278 if A != 1 || B != 2 { 1279 t.Fatal("expected", 1, 2,"got", A, B) 1280 } 1281 } 1282 `) 1283 gb.cd(gb.tempdir) 1284 tmpdir := gb.tempDir("tmp") 1285 gb.setenv("TMP", tmpdir) 1286 gb.run("test", "-race", "x") 1287 gb.grepStdout("^x$", "expected x") // output from gb test 1288 gb.mustBeEmpty(tmpdir) 1289 gb.mustNotExist(filepath.Join(gb.tempdir, "pkg")) // ensure no pkg directory is created 1290 } 1291 1292 // check that go test -race builds and runs a racy binary, and that it finds the race. 1293 func TestTestRace(t *testing.T) { 1294 if !canRace { 1295 t.Skip("skipping because race detector not supported") 1296 } 1297 if strings.HasPrefix(runtime.Version(), "go1.4") { 1298 t.Skipf("skipping race test as Go version %v incorrectly marks race failures as success", runtime.Version()) 1299 } 1300 1301 gb := T{T: t} 1302 defer gb.cleanup() 1303 1304 gb.tempDir("src/race") 1305 gb.tempFile("src/race/map_test.go", `package race 1306 import "testing" 1307 1308 func TestRaceMapRW(t *testing.T) { 1309 m := make(map[int]int) 1310 ch := make(chan bool, 1) 1311 go func() { 1312 _ = m[1] 1313 ch <- true 1314 }() 1315 m[1] = 1 1316 <-ch 1317 } 1318 `) 1319 gb.cd(gb.tempdir) 1320 tmpdir := gb.tempDir("tmp") 1321 gb.setenv("TMP", tmpdir) 1322 gb.runFail("test", "-race") 1323 gb.mustBeEmpty(tmpdir) 1324 } 1325 1326 // check that missing -race support generates error message. 1327 func TestRaceMissing(t *testing.T) { 1328 if canRace { 1329 t.Skip("skipping because race detector is available") 1330 } 1331 1332 gb := T{T: t} 1333 defer gb.cleanup() 1334 1335 gb.tempDir("src/race") 1336 gb.tempFile("src/race/map_test.go", `package race 1337 import "testing" 1338 1339 func TestRaceMapRW(t *testing.T) { 1340 m := make(map[int]int) 1341 ch := make(chan bool, 1) 1342 go func() { 1343 _ = m[1] 1344 ch <- true 1345 }() 1346 m[1] = 1 1347 <-ch 1348 } 1349 `) 1350 gb.cd(gb.tempdir) 1351 tmpdir := gb.tempDir("tmp") 1352 gb.setenv("TMP", tmpdir) 1353 gb.runFail("test", "-race") 1354 gb.grepStderr(regexp.QuoteMeta(fmt.Sprintf("FATAL: go installation at %s is missing race support", runtime.GOROOT())), "expected missing race support message") 1355 gb.mustBeEmpty(tmpdir) 1356 } 1357 1358 // test that gb will no build the stdlib directly, only as transitive deps. 1359 func TestNoBuildStdlib(t *testing.T) { 1360 t.Skip("constabulary/gb#505") 1361 gb := T{T: t} 1362 defer gb.cleanup() 1363 gb.tempDir("src/") 1364 gb.cd(gb.tempdir) 1365 defer gb.cleanup() 1366 gb.runFail("build", "-f", "-F", "net/http") 1367 } 1368 1369 func TestCrossCompile(t *testing.T) { 1370 if strings.HasPrefix(runtime.Version(), "go1.4") { 1371 t.Skip("skipping cross compile test, not supported on", runtime.Version()) 1372 } 1373 gb := T{T: t} 1374 defer gb.cleanup() 1375 gb.tempDir("src/p") 1376 gb.tempFile("src/p/main.go", `package main 1377 func main() { println("hello world") } 1378 `) 1379 gb.cd(gb.tempdir) 1380 tmpdir := gb.tempDir("tmp") 1381 goos := "windows" 1382 if runtime.GOOS == goos { 1383 goos = "linux" 1384 } 1385 goarch := "386" 1386 if runtime.GOARCH == goarch { 1387 goarch = "amd64" 1388 } 1389 gb.setenv("TMP", tmpdir) 1390 gb.setenv("GOOS", goos) 1391 gb.setenv("GOARCH", goarch) 1392 gb.run("build") 1393 gb.mustBeEmpty(tmpdir) 1394 name := fmt.Sprintf("p-%s-%s", goos, goarch) 1395 if goos == "windows" { 1396 name += ".exe" 1397 } 1398 gb.mustExist(gb.path("bin", name)) 1399 gb.wantExecutable(gb.path("bin", name), "expected $PROJECT/bin/p-$GOOS-$GOARCH") 1400 } 1401 1402 // https://github.com/constabulary/gb/issues/416 1403 func TestGbBuildBuildsPackgeCalledCmd(t *testing.T) { 1404 gb := T{T: t} 1405 defer gb.cleanup() 1406 gb.tempDir("src/cmd") 1407 gb.tempFile("src/cmd/main.go", `package main 1408 func main() { println("hello world") } 1409 `) 1410 gb.cd(gb.tempdir) 1411 tmpdir := gb.tempDir("tmp") 1412 gb.setenv("TMP", tmpdir) 1413 gb.run("build") 1414 gb.mustBeEmpty(tmpdir) 1415 gb.grepStdout("^cmd$", "expected cmd") 1416 name := "cmd" 1417 if runtime.GOOS == "windows" { 1418 name += ".exe" 1419 } 1420 gb.mustExist(gb.path("bin", name)) 1421 gb.wantExecutable(gb.path("bin", name), "expected $PROJECT/bin/"+name) 1422 } 1423 1424 // https://github.com/constabulary/gb/issues/492 1425 func TestGbBuildSubPackageOfCmd(t *testing.T) { 1426 gb := T{T: t} 1427 defer gb.cleanup() 1428 gb.tempDir("src/cmd/hello") 1429 gb.tempFile("src/cmd/hello/main.go", `package main 1430 func main() { println("hello world") } 1431 `) 1432 gb.cd(gb.tempdir) 1433 tmpdir := gb.tempDir("tmp") 1434 gb.setenv("TMP", tmpdir) 1435 gb.run("build") 1436 gb.mustBeEmpty(tmpdir) 1437 name := "hello" 1438 if runtime.GOOS == "windows" { 1439 name += ".exe" 1440 } 1441 gb.wantExecutable(gb.path("bin", name), "expected $PROJECT/bin/hello") 1442 } 1443 1444 // https://github.com/constabulary/gb/issues/515 1445 func TestIssue515(t *testing.T) { 1446 gb := T{T: t} 1447 defer gb.cleanup() 1448 gb.tempDir("src/main") 1449 gb.tempFile("src/main/main.go", `package main 1450 1451 import ( 1452 "log" 1453 "net/http" 1454 ) 1455 1456 func main() { 1457 err := http.ListenAndServe(":8080", nil) 1458 if err != nil { 1459 log.Fatal("ListenAndServe: ", err) 1460 } else { 1461 log.Print("Server started!") 1462 } 1463 } 1464 `) 1465 gb.cd(gb.tempdir) 1466 tmpdir := gb.tempDir("tmp") 1467 gb.setenv("TMP", tmpdir) 1468 gb.run("build") 1469 gb.mustBeEmpty(tmpdir) 1470 name := "main" 1471 if runtime.GOOS == "windows" { 1472 name += ".exe" 1473 } 1474 gb.wantExecutable(gb.path("bin", name), "expected $PROJECT/bin/main") 1475 } 1476 1477 func TestGbGenerate(t *testing.T) { 1478 if runtime.GOOS == "windows" { 1479 t.Skipf("windows doesn't have echo, lol") 1480 } 1481 gb := T{T: t} 1482 defer gb.cleanup() 1483 gb.tempDir("src/gentest") 1484 gb.tempFile("src/gentest/generate.go", `package gentest 1485 //go:generate echo $GOPACKAGE $GOFILE 1486 `) 1487 gb.cd(gb.tempdir) 1488 gb.run("generate") 1489 gb.grepStdout("^gentest generate.go$", "expected $GOPACKAGE $GOFILE") 1490 } 1491 1492 func TestGbDoc(t *testing.T) { 1493 if runtime.GOOS == "windows" { 1494 t.Skipf("windows doesn't have echo, lol") 1495 } 1496 gb := T{T: t} 1497 defer gb.cleanup() 1498 gb.tempDir("src/doctest") 1499 gb.tempFile("src/doctest/doc.go", `// Package doctest tests gb doc 1500 package doctest 1501 `) 1502 gb.cd(gb.tempdir) 1503 gb.run("doc", "doctest") 1504 gb.grepStdout("Package doctest tests gb doc$", "expected Package doctest tests gb doc") 1505 } 1506 1507 func TestIssue346(t *testing.T) { 1508 gb := T{T: t} 1509 defer gb.cleanup() 1510 gb.tempDir("src/p") 1511 gb.tempFile("src/p/main.go", `package main 1512 func main() { println("hello world") } 1513 `) 1514 gb.cd(gb.tempdir) 1515 tmpdir := gb.tempDir("tmp") 1516 gb.setenv("TMP", tmpdir) 1517 1518 goos := runtime.GOOS 1519 1520 // scenario 1: GOOS/GOARCH not set 1521 name := "p" 1522 if goos == "windows" { 1523 name += ".exe" 1524 } 1525 gb.unsetenv("GOOS") 1526 gb.unsetenv("GOARCH") 1527 gb.run("build") 1528 gb.wantExecutable(gb.path("bin", name), "expected $PROJECT/bin/p") 1529 1530 // scenario 2: GOOS/GOARCH are both set 1531 name = fmt.Sprintf("p-%s-%s", goos, runtime.GOARCH) 1532 if goos == "windows" { 1533 name += ".exe" 1534 } 1535 gb.setenv("GOOS", goos) 1536 gb.setenv("GOARCH", runtime.GOARCH) 1537 gb.run("build") 1538 gb.wantExecutable(gb.path("bin", name), "expected $PROJECT/bin/p-$GOOS-$GOARCH") 1539 1540 // scenario 3: just GOOS is set 1541 os.Remove(gb.path("bin", name)) 1542 gb.unsetenv("GOARCH") 1543 gb.run("build") 1544 gb.mustNotExist(gb.path("bin", name)) 1545 } 1546 1547 func TestGbBuildCannotReferencePackagesInGoroot(t *testing.T) { 1548 gb := T{T: t} 1549 defer gb.cleanup() 1550 1551 gb.tempDir("src") 1552 gb.cd(gb.tempdir) 1553 tmpdir := gb.tempDir("tmp") 1554 1555 gb.setenv("TMP", tmpdir) 1556 gb.runFail("build", "net/http") // net/http will be excluded by resolveRootPackages 1557 gb.mustBeEmpty(tmpdir) 1558 gb.mustNotExist(gb.path("pkg")) 1559 gb.grepStderr(`FATAL: command "build" failed: no packages supplied`, "expected FATAL") 1560 } 1561 1562 func TestGbBuildWillResolvePackagesInVendorAsRoots(t *testing.T) { 1563 gb := T{T: t} 1564 defer gb.cleanup() 1565 1566 gb.tempDir("src") 1567 gb.tempDir("vendor/src/test/test1") 1568 gb.tempFile("vendor/src/test/test1/test1.go", `package http 1569 func init() { 1570 println("Hello, world!") 1571 } 1572 `) 1573 gb.cd(gb.tempdir) 1574 tmpdir := gb.tempDir("tmp") 1575 1576 gb.setenv("TMP", tmpdir) 1577 gb.runFail("build") // should fail, nothing supplied 1578 gb.mustBeEmpty(tmpdir) 1579 gb.mustNotExist(gb.path("pkg")) 1580 gb.grepStderr(`FATAL: command "build" failed: no packages supplied`, "expected FATAL") 1581 1582 gb.runFail("build", "test/...") // should fail, globbing does not match $PROJECT/vendor/src 1583 gb.mustBeEmpty(tmpdir) 1584 gb.mustNotExist(gb.path("pkg")) 1585 gb.grepStderr(`FATAL: command "build" failed: no packages supplied`, "expected FATAL") 1586 1587 gb.run("build", "test/test1") // should resolve to vendor/src/test/test1 1588 gb.mustBeEmpty(tmpdir) 1589 gb.wantArchive(filepath.Join(gb.tempdir, "pkg", runtime.GOOS+"-"+runtime.GOARCH, "test", "test1.a")) 1590 gb.grepStdout(`^test/test`, "expected test/test1") 1591 } 1592 1593 func TestIssue550(t *testing.T) { 1594 gb := T{T: t} 1595 defer gb.cleanup() 1596 1597 gb.tempDir("src/x") 1598 gb.tempFile("src/x/x.go", `package main 1599 1600 import ( 1601 "log" 1602 "this/is/a/bad/path" 1603 ) 1604 1605 func main() { 1606 log.Println("Hello World.") 1607 } 1608 `) 1609 gb.cd(gb.tempdir) 1610 tmpdir := gb.tempDir("tmp") 1611 1612 gb.setenv("TMP", tmpdir) 1613 name := "x" 1614 if runtime.GOOS == "windows" { 1615 name += ".exe" 1616 } 1617 gb.runFail("build") 1618 gb.mustBeEmpty(tmpdir) 1619 gb.grepStderr(`FATAL: command "build" failed: failed to resolve import path "x": import "this/is/a/bad/path": not found`, "expected FATAL") 1620 }