LEFT | RIGHT |
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package main | 5 package main |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "fmt" | 9 "fmt" |
10 "go/ast" | 10 "go/ast" |
11 "go/build" | 11 "go/build" |
12 "go/doc" | 12 "go/doc" |
13 "go/parser" | 13 "go/parser" |
14 "go/scanner" | |
15 "go/token" | 14 "go/token" |
16 "os" | 15 "os" |
17 "os/exec" | 16 "os/exec" |
18 "path" | 17 "path" |
19 "path/filepath" | 18 "path/filepath" |
20 "runtime" | 19 "runtime" |
21 "sort" | 20 "sort" |
22 "strings" | 21 "strings" |
23 "text/template" | 22 "text/template" |
24 "time" | 23 "time" |
25 "unicode" | 24 "unicode" |
26 "unicode/utf8" | 25 "unicode/utf8" |
27 ) | 26 ) |
28 | 27 |
29 // Break init loop. | 28 // Break init loop. |
30 func init() { | 29 func init() { |
31 cmdTest.Run = runTest | 30 cmdTest.Run = runTest |
32 } | 31 } |
33 | 32 |
34 var cmdTest = &Command{ | 33 var cmdTest = &Command{ |
35 CustomFlags: true, | 34 CustomFlags: true, |
36 » UsageLine: "test [-c] [-i] [-p n] [-x] [importpath...] [flags for test
binary]", | 35 » UsageLine: "test [-c] [-i] [build flags] [packages] [flags for test bi
nary]", |
37 Short: "test packages", | 36 Short: "test packages", |
38 Long: ` | 37 Long: ` |
39 'Go test' automates testing the packages named by the import paths. | 38 'Go test' automates testing the packages named by the import paths. |
40 It prints a summary of the test results in the format: | 39 It prints a summary of the test results in the format: |
41 | 40 |
42 ok archive/tar 0.011s | 41 ok archive/tar 0.011s |
43 FAIL archive/zip 0.022s | 42 FAIL archive/zip 0.022s |
44 ok compress/gzip 0.033s | 43 ok compress/gzip 0.033s |
45 ... | 44 ... |
46 | 45 |
47 followed by detailed output for each failed package. | 46 followed by detailed output for each failed package. |
48 | 47 |
49 'Go test' recompiles each package along with any files with names matching | 48 'Go test' recompiles each package along with any files with names matching |
50 the file pattern "*_test.go". These additional files can contain test functions
, | 49 the file pattern "*_test.go". These additional files can contain test functions
, |
51 benchmark functions, and example functions. See 'go help testfunc' for more. | 50 benchmark functions, and example functions. See 'go help testfunc' for more. |
52 | 51 |
53 By default, go test needs no arguments. It compiles and tests the package | 52 By default, go test needs no arguments. It compiles and tests the package |
54 with source in the current directory, including tests, and runs the tests. | 53 with source in the current directory, including tests, and runs the tests. |
55 | 54 |
56 The package is built in a temporary directory so it does not interfere with the | 55 The package is built in a temporary directory so it does not interfere with the |
57 non-test installation. | 56 non-test installation. |
58 | 57 |
59 The flags handled by 'go test' itself are: | 58 In addition to the build flags, the flags handled by 'go test' itself are: |
60 | 59 |
61 -c Compile the test binary to pkg.test but do not run it. | 60 -c Compile the test binary to pkg.test but do not run it. |
62 | 61 |
63 -i | 62 -i |
64 Install packages that are dependencies of the test. | 63 Install packages that are dependencies of the test. |
65 Do not run the test. | 64 Do not run the test. |
66 | 65 |
67 -p n | |
68 Compile and test up to n packages in parallel. | |
69 The default value is the number of CPUs available. | |
70 | |
71 -x Print each subcommand go test executes. | |
72 | |
73 The test binary also accepts flags that control execution of the test; these | 66 The test binary also accepts flags that control execution of the test; these |
74 flags are also accessible by 'go test'. See 'go help testflag' for details. | 67 flags are also accessible by 'go test'. See 'go help testflag' for details. |
75 | 68 |
76 See 'go help importpath' for more about import paths. | 69 For more about build flags, see 'go help build'. |
| 70 For more about specifying packages, see 'go help packages'. |
77 | 71 |
78 See also: go build, go vet. | 72 See also: go build, go vet. |
79 `, | 73 `, |
80 } | 74 } |
81 | 75 |
82 var helpTestflag = &Command{ | 76 var helpTestflag = &Command{ |
83 UsageLine: "testflag", | 77 UsageLine: "testflag", |
84 Short: "description of testing flags", | 78 Short: "description of testing flags", |
85 Long: ` | 79 Long: ` |
86 The 'go test' command takes both flags that apply to 'go test' itself | 80 The 'go test' command takes both flags that apply to 'go test' itself |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 exhaustive tests. | 121 exhaustive tests. |
128 | 122 |
129 -test.timeout t | 123 -test.timeout t |
130 If a test runs longer than t, panic. | 124 If a test runs longer than t, panic. |
131 | 125 |
132 -test.benchtime n | 126 -test.benchtime n |
133 Run enough iterations of each benchmark to take n seconds. | 127 Run enough iterations of each benchmark to take n seconds. |
134 The default is 1 second. | 128 The default is 1 second. |
135 | 129 |
136 -test.cpu 1,2,4 | 130 -test.cpu 1,2,4 |
137 » Specify a list of GOMAXPROCS values for which the tests or | 131 » Specify a list of GOMAXPROCS values for which the tests or |
138 benchmarks should be executed. The default is the current value | 132 benchmarks should be executed. The default is the current value |
139 of GOMAXPROCS. | 133 of GOMAXPROCS. |
140 | 134 |
141 For convenience, each of these -test.X flags of the test binary is | 135 For convenience, each of these -test.X flags of the test binary is |
142 also available as the flag -X in 'go test' itself. Flags not listed | 136 also available as the flag -X in 'go test' itself. Flags not listed |
143 here are passed through unaltered. For instance, the command | 137 here are passed through unaltered. For instance, the command |
144 | 138 |
145 go test -x -v -cpuprofile=prof.out -dir=testdata -update | 139 go test -x -v -cpuprofile=prof.out -dir=testdata -update |
146 | 140 |
147 will compile the test binary and then run it as | 141 will compile the test binary and then run it as |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 } | 294 } |
301 b.init() | 295 b.init() |
302 } | 296 } |
303 | 297 |
304 var builds, runs, prints []*action | 298 var builds, runs, prints []*action |
305 | 299 |
306 // Prepare build + run + print actions for all packages being tested. | 300 // Prepare build + run + print actions for all packages being tested. |
307 for _, p := range pkgs { | 301 for _, p := range pkgs { |
308 buildTest, runTest, printTest, err := b.test(p) | 302 buildTest, runTest, printTest, err := b.test(p) |
309 if err != nil { | 303 if err != nil { |
310 » » » if list, ok := err.(scanner.ErrorList); ok { | 304 » » » str := err.Error() |
311 » » » » const n = 10 | 305 » » » if strings.HasPrefix(str, "\n") { |
312 » » » » if len(list) > n { | 306 » » » » str = str[1:] |
313 » » » » » list = list[:n] | |
314 » » » » } | |
315 » » » » for _, err := range list { | |
316 » » » » » errorf("%s", err) | |
317 » » » » } | |
318 » » » » continue | |
319 } | 307 } |
320 » » » errorf("%s", err) | 308 » » » if p.ImportPath != "" { |
| 309 » » » » errorf("# %s\n%s", p.ImportPath, str) |
| 310 » » » } else { |
| 311 » » » » errorf("%s", str) |
| 312 » » » } |
321 continue | 313 continue |
322 } | 314 } |
323 builds = append(builds, buildTest) | 315 builds = append(builds, buildTest) |
324 runs = append(runs, runTest) | 316 runs = append(runs, runTest) |
325 prints = append(prints, printTest) | 317 prints = append(prints, printTest) |
326 } | 318 } |
327 | 319 |
328 // Ultimately the goal is to print the output. | 320 // Ultimately the goal is to print the output. |
329 root := &action{deps: prints} | 321 root := &action{deps: prints} |
330 | 322 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 print := &action{f: (*builder).notest, p: p, deps: []*action{bui
ld}} | 378 print := &action{f: (*builder).notest, p: p, deps: []*action{bui
ld}} |
387 return build, run, print, nil | 379 return build, run, print, nil |
388 } | 380 } |
389 | 381 |
390 // Build Package structs describing: | 382 // Build Package structs describing: |
391 // ptest - package + test files | 383 // ptest - package + test files |
392 // pxtest - package of external test files | 384 // pxtest - package of external test files |
393 // pmain - pkg.test binary | 385 // pmain - pkg.test binary |
394 var ptest, pxtest, pmain *Package | 386 var ptest, pxtest, pmain *Package |
395 | 387 |
396 » // go/build does not distinguish the dependencies used | 388 » var imports, ximports []*Package |
397 » // by the TestGoFiles from the dependencies used by the | |
398 » // XTestGoFiles, so we build one list and use it for both | |
399 » // ptest and pxtest. No harm done. | |
400 » var imports []*Package | |
401 var stk importStack | 389 var stk importStack |
402 stk.push(p.ImportPath + "_test") | 390 stk.push(p.ImportPath + "_test") |
403 for _, path := range p.TestImports { | 391 for _, path := range p.TestImports { |
404 » » p1 := loadImport(path, p.Dir, &stk) | 392 » » p1 := loadImport(path, p.Dir, &stk, p.build.TestImportPos[path]) |
405 if p1.Error != nil { | 393 if p1.Error != nil { |
406 return nil, nil, nil, p1.Error | 394 return nil, nil, nil, p1.Error |
407 } | 395 } |
408 imports = append(imports, p1) | 396 imports = append(imports, p1) |
| 397 } |
| 398 for _, path := range p.XTestImports { |
| 399 p1 := loadImport(path, p.Dir, &stk, p.build.XTestImportPos[path]
) |
| 400 if p1.Error != nil { |
| 401 return nil, nil, nil, p1.Error |
| 402 } |
| 403 ximports = append(ximports, p1) |
409 } | 404 } |
410 stk.pop() | 405 stk.pop() |
411 | 406 |
412 // Use last element of import path, not package name. | 407 // Use last element of import path, not package name. |
413 // They differ when package name is "main". | 408 // They differ when package name is "main". |
414 _, elem := path.Split(p.ImportPath) | 409 _, elem := path.Split(p.ImportPath) |
415 testBinary := elem + ".test" | 410 testBinary := elem + ".test" |
416 | 411 |
417 // The ptest package needs to be importable under the | 412 // The ptest package needs to be importable under the |
418 // same import path that p has, but we cannot put it in | 413 // same import path that p has, but we cannot put it in |
(...skipping 26 matching lines...) Expand all Loading... |
445 ptest = new(Package) | 440 ptest = new(Package) |
446 *ptest = *p | 441 *ptest = *p |
447 ptest.GoFiles = nil | 442 ptest.GoFiles = nil |
448 ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...) | 443 ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...) |
449 ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...) | 444 ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...) |
450 ptest.target = "" | 445 ptest.target = "" |
451 ptest.Imports = stringList(p.Imports, p.TestImports) | 446 ptest.Imports = stringList(p.Imports, p.TestImports) |
452 ptest.imports = append(append([]*Package{}, p.imports...), impor
ts...) | 447 ptest.imports = append(append([]*Package{}, p.imports...), impor
ts...) |
453 ptest.pkgdir = testDir | 448 ptest.pkgdir = testDir |
454 ptest.fake = true | 449 ptest.fake = true |
| 450 ptest.build = new(build.Package) |
| 451 *ptest.build = *p.build |
| 452 m := map[string][]token.Position{} |
| 453 for k, v := range p.build.ImportPos { |
| 454 m[k] = append(m[k], v...) |
| 455 } |
| 456 for k, v := range p.build.TestImportPos { |
| 457 m[k] = append(m[k], v...) |
| 458 } |
| 459 ptest.build.ImportPos = m |
455 a := b.action(modeBuild, modeBuild, ptest) | 460 a := b.action(modeBuild, modeBuild, ptest) |
456 a.objdir = testDir + string(filepath.Separator) | 461 a.objdir = testDir + string(filepath.Separator) |
457 a.objpkg = ptestObj | 462 a.objpkg = ptestObj |
458 a.target = ptestObj | 463 a.target = ptestObj |
459 a.link = false | 464 a.link = false |
460 } else { | 465 } else { |
461 ptest = p | 466 ptest = p |
462 } | 467 } |
463 | 468 |
464 // External test package. | 469 // External test package. |
465 if len(p.XTestGoFiles) > 0 { | 470 if len(p.XTestGoFiles) > 0 { |
466 pxtest = &Package{ | 471 pxtest = &Package{ |
467 Name: p.Name + "_test", | 472 Name: p.Name + "_test", |
468 ImportPath: p.ImportPath + "_test", | 473 ImportPath: p.ImportPath + "_test", |
469 Dir: p.Dir, | 474 Dir: p.Dir, |
470 GoFiles: p.XTestGoFiles, | 475 GoFiles: p.XTestGoFiles, |
471 » » » Imports: p.TestImports, | 476 » » » Imports: p.XTestImports, |
472 » » » build: &build.Package{}, | 477 » » » build: &build.Package{ |
473 » » » imports: imports, | 478 » » » » ImportPos: p.build.XTestImportPos, |
474 » » » pkgdir: testDir, | 479 » » » }, |
475 » » » fake: true, | 480 » » » imports: append(ximports, ptest), |
476 » » } | 481 » » » pkgdir: testDir, |
477 » » pxtest.imports = append(pxtest.imports, ptest) | 482 » » » fake: true, |
| 483 » » } |
478 a := b.action(modeBuild, modeBuild, pxtest) | 484 a := b.action(modeBuild, modeBuild, pxtest) |
479 a.objdir = testDir + string(filepath.Separator) | 485 a.objdir = testDir + string(filepath.Separator) |
480 a.objpkg = buildToolchain.pkgpath(testDir, pxtest, false) | 486 a.objpkg = buildToolchain.pkgpath(testDir, pxtest, false) |
481 a.target = a.objpkg | 487 a.target = a.objpkg |
482 } | 488 } |
483 | 489 |
484 // Action for building pkg.test. | 490 // Action for building pkg.test. |
485 pmain = &Package{ | 491 pmain = &Package{ |
486 Name: "main", | 492 Name: "main", |
487 Dir: testDir, | 493 Dir: testDir, |
488 GoFiles: []string{"_testmain.go"}, | 494 GoFiles: []string{"_testmain.go"}, |
| 495 imports: []*Package{ptest}, |
489 build: &build.Package{}, | 496 build: &build.Package{}, |
490 imports: []*Package{ptest}, | |
491 fake: true, | 497 fake: true, |
492 } | 498 } |
493 if pxtest != nil { | 499 if pxtest != nil { |
494 pmain.imports = append(pmain.imports, pxtest) | 500 pmain.imports = append(pmain.imports, pxtest) |
495 } | 501 } |
496 | 502 |
497 // The generated main also imports testing and regexp. | 503 // The generated main also imports testing and regexp. |
498 stk.push("testmain") | 504 stk.push("testmain") |
499 » ptesting := loadImport("testing", "", &stk) | 505 » ptesting := loadImport("testing", "", &stk, nil) |
500 if ptesting.Error != nil { | 506 if ptesting.Error != nil { |
501 return nil, nil, nil, ptesting.Error | 507 return nil, nil, nil, ptesting.Error |
502 } | 508 } |
503 » pregexp := loadImport("regexp", "", &stk) | 509 » pregexp := loadImport("regexp", "", &stk, nil) |
504 if pregexp.Error != nil { | 510 if pregexp.Error != nil { |
505 return nil, nil, nil, pregexp.Error | 511 return nil, nil, nil, pregexp.Error |
506 } | 512 } |
507 pmain.imports = append(pmain.imports, ptesting, pregexp) | 513 pmain.imports = append(pmain.imports, ptesting, pregexp) |
508 | 514 |
509 a := b.action(modeBuild, modeBuild, pmain) | 515 a := b.action(modeBuild, modeBuild, pmain) |
510 a.objdir = testDir + string(filepath.Separator) | 516 a.objdir = testDir + string(filepath.Separator) |
511 a.objpkg = filepath.Join(testDir, "main.a") | 517 a.objpkg = filepath.Join(testDir, "main.a") |
512 » a.target = filepath.Join(testDir, testBinary) + b.exe | 518 » a.target = filepath.Join(testDir, testBinary) + exeSuffix |
513 pmainAction := a | 519 pmainAction := a |
514 | 520 |
515 if testC { | 521 if testC { |
516 // -c flag: create action to copy binary to ./test.out. | 522 // -c flag: create action to copy binary to ./test.out. |
517 runAction = &action{ | 523 runAction = &action{ |
518 f: (*builder).install, | 524 f: (*builder).install, |
519 deps: []*action{pmainAction}, | 525 deps: []*action{pmainAction}, |
520 p: pmain, | 526 p: pmain, |
521 » » » target: testBinary + b.exe, | 527 » » » target: testBinary + exeSuffix, |
522 } | 528 } |
523 printAction = &action{p: p, deps: []*action{runAction}} // nop | 529 printAction = &action{p: p, deps: []*action{runAction}} // nop |
524 } else { | 530 } else { |
525 // run test | 531 // run test |
526 runAction = &action{ | 532 runAction = &action{ |
527 f: (*builder).runTest, | 533 f: (*builder).runTest, |
528 deps: []*action{pmainAction}, | 534 deps: []*action{pmainAction}, |
529 p: p, | 535 p: p, |
530 ignoreFail: true, | 536 ignoreFail: true, |
531 } | 537 } |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 Package string // imported package name (_test or _xtest) | 706 Package string // imported package name (_test or _xtest) |
701 Name string // function name | 707 Name string // function name |
702 Output string // output, for examples | 708 Output string // output, for examples |
703 } | 709 } |
704 | 710 |
705 var testFileSet = token.NewFileSet() | 711 var testFileSet = token.NewFileSet() |
706 | 712 |
707 func (t *testFuncs) load(filename, pkg string, seen *bool) error { | 713 func (t *testFuncs) load(filename, pkg string, seen *bool) error { |
708 f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComme
nts) | 714 f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComme
nts) |
709 if err != nil { | 715 if err != nil { |
710 » » return err | 716 » » return expandScanner(err) |
711 } | 717 } |
712 for _, d := range f.Decls { | 718 for _, d := range f.Decls { |
713 n, ok := d.(*ast.FuncDecl) | 719 n, ok := d.(*ast.FuncDecl) |
714 if !ok { | 720 if !ok { |
715 continue | 721 continue |
716 } | 722 } |
717 if n.Recv != nil { | 723 if n.Recv != nil { |
718 continue | 724 continue |
719 } | 725 } |
720 name := n.Name.String() | 726 name := n.Name.String() |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 } | 789 } |
784 } | 790 } |
785 return matchRe.MatchString(str), nil | 791 return matchRe.MatchString(str), nil |
786 } | 792 } |
787 | 793 |
788 func main() { | 794 func main() { |
789 testing.Main(matchString, tests, benchmarks, examples) | 795 testing.Main(matchString, tests, benchmarks, examples) |
790 } | 796 } |
791 | 797 |
792 `)) | 798 `)) |
LEFT | RIGHT |