1
0
mirror of https://github.com/golang/go synced 2024-11-21 20:04:44 -07:00

cmd/go: two testing fixes

1. Show passing output for "go test" (no args) and with -v flag.
2. Warn about out-of-date packages being rebuilt.

R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/5504080
This commit is contained in:
Russ Cox 2011-12-22 22:24:43 -05:00
parent 3800b14071
commit eef7184046
4 changed files with 102 additions and 30 deletions

View File

@ -336,6 +336,26 @@ func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action
return a return a
} }
// actionList returns the list of actions in the dag rooted at root
// as visited in a depth-first post-order traversal.
func actionList(root *action) []*action {
seen := map[*action]bool{}
all := []*action{}
var walk func(*action)
walk = func(a *action) {
if seen[a] {
return
}
seen[a] = true
for _, a1 := range a.deps {
walk(a1)
}
all = append(all, a)
}
walk(root)
return all
}
// do runs the action graph rooted at root. // do runs the action graph rooted at root.
func (b *builder) do(root *action) { func (b *builder) do(root *action) {
// Build list of all actions, assigning depth-first post-order priority. // Build list of all actions, assigning depth-first post-order priority.
@ -349,27 +369,16 @@ func (b *builder) do(root *action) {
// ensure that, all else being equal, the execution prefers // ensure that, all else being equal, the execution prefers
// to do what it would have done first in a simple depth-first // to do what it would have done first in a simple depth-first
// dependency order traversal. // dependency order traversal.
all := map[*action]bool{} all := actionList(root)
priority := 0 for i, a := range all {
var walk func(*action) a.priority = i
walk = func(a *action) {
if all[a] {
return
}
all[a] = true
priority++
for _, a1 := range a.deps {
walk(a1)
}
a.priority = priority
} }
walk(root)
b.readySema = make(chan bool, len(all)) b.readySema = make(chan bool, len(all))
done := make(chan bool) done := make(chan bool)
// Initialize per-action execution state. // Initialize per-action execution state.
for a := range all { for _, a := range all {
for _, a1 := range a.deps { for _, a1 := range a.deps {
a1.triggers = append(a1.triggers, a) a1.triggers = append(a1.triggers, a)
} }

View File

@ -48,6 +48,7 @@ type Package struct {
imports []*Package imports []*Package
gofiles []string // GoFiles+CgoFiles, absolute paths gofiles []string // GoFiles+CgoFiles, absolute paths
target string // installed file for this package (may be executable) target string // installed file for this package (may be executable)
fake bool // synthesized package
} }
// packageCache is a lookup cache for loadPackage, // packageCache is a lookup cache for loadPackage,

View File

@ -193,25 +193,28 @@ See the documentation of the testing package for more information.
// For now just use the gotest code. // For now just use the gotest code.
var ( var (
testC bool // -c flag testC bool // -c flag
testX bool // -x flag testX bool // -x flag
testFiles []string // -file flag(s) TODO: not respected testV bool // -v flag
testArgs []string testFiles []string // -file flag(s) TODO: not respected
testArgs []string
testShowPass bool // whether to display passing output
) )
func runTest(cmd *Command, args []string) { func runTest(cmd *Command, args []string) {
// Determine which are the import paths var pkgArgs []string
// (leading arguments not starting with -). pkgArgs, testArgs = testFlags(args)
i := 0
for i < len(args) && !strings.HasPrefix(args[i], "-") { // show test PASS output when no packages
i++ // are listed (implicitly current directory: "go test")
} // or when the -v flag has been given.
pkgs := packages(args[:i]) testShowPass = len(pkgArgs) == 0 || testV
pkgs := packages(pkgArgs)
if len(pkgs) == 0 { if len(pkgs) == 0 {
fatalf("no packages to test") fatalf("no packages to test")
} }
testArgs = testFlags(args[i:])
if testC && len(pkgs) != 1 { if testC && len(pkgs) != 1 {
fatalf("cannot use -c flag with multiple packages") fatalf("cannot use -c flag with multiple packages")
} }
@ -243,9 +246,31 @@ func runTest(cmd *Command, args []string) {
a.deps = append(a.deps, runs[i-1]) a.deps = append(a.deps, runs[i-1])
} }
} }
root := &action{deps: runs}
allRuns := &action{deps: runs} // If we are building any out-of-date packages other
b.do(allRuns) // than those under test, warn.
okBuild := map[*Package]bool{}
for _, p := range pkgs {
okBuild[p] = true
}
warned := false
for _, a := range actionList(root) {
if a.p != nil && a.f != nil && !okBuild[a.p] && !a.p.fake {
okBuild[a.p] = true // don't warn again
if !warned {
fmt.Fprintf(os.Stderr, "warning: building out-of-date packages:\n")
warned = true
}
fmt.Fprintf(os.Stderr, "\t%s\n", a.p.ImportPath)
}
}
if warned {
fmt.Fprintf(os.Stderr, "installing these packages with 'go install' will speed future tests.\n\n")
}
b.do(root)
} }
func (b *builder) test(p *Package) (buildAction, runAction *action, err error) { func (b *builder) test(p *Package) (buildAction, runAction *action, err error) {
@ -312,6 +337,7 @@ func (b *builder) test(p *Package) (buildAction, runAction *action, err error) {
ptest.Imports = append(append([]string{}, p.info.Imports...), p.info.TestImports...) ptest.Imports = append(append([]string{}, p.info.Imports...), p.info.TestImports...)
ptest.imports = append(append([]*Package{}, p.imports...), imports...) ptest.imports = append(append([]*Package{}, p.imports...), imports...)
ptest.pkgdir = testDir ptest.pkgdir = testDir
ptest.fake = true
a := b.action(modeBuild, modeBuild, ptest) a := b.action(modeBuild, modeBuild, ptest)
a.objdir = testDir + string(filepath.Separator) a.objdir = testDir + string(filepath.Separator)
a.objpkg = ptestObj a.objpkg = ptestObj
@ -333,6 +359,7 @@ func (b *builder) test(p *Package) (buildAction, runAction *action, err error) {
info: &build.DirInfo{}, info: &build.DirInfo{},
imports: imports, imports: imports,
pkgdir: testDir, pkgdir: testDir,
fake: true,
} }
pxtest.imports = append(pxtest.imports, ptest) pxtest.imports = append(pxtest.imports, ptest)
a := b.action(modeBuild, modeBuild, pxtest) a := b.action(modeBuild, modeBuild, pxtest)
@ -349,6 +376,7 @@ func (b *builder) test(p *Package) (buildAction, runAction *action, err error) {
t: p.t, t: p.t,
info: &build.DirInfo{}, info: &build.DirInfo{},
imports: []*Package{ptest}, imports: []*Package{ptest},
fake: true,
} }
if pxtest != nil { if pxtest != nil {
pmain.imports = append(pmain.imports, pxtest) pmain.imports = append(pmain.imports, pxtest)
@ -407,6 +435,9 @@ func (b *builder) runTest(a *action) error {
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if err == nil && (bytes.Equal(out, pass[1:]) || bytes.HasSuffix(out, pass)) { if err == nil && (bytes.Equal(out, pass[1:]) || bytes.HasSuffix(out, pass)) {
fmt.Printf("ok \t%s\n", a.p.ImportPath) fmt.Printf("ok \t%s\n", a.p.ImportPath)
if testShowPass {
os.Stdout.Write(out)
}
return nil return nil
} }

View File

@ -78,10 +78,39 @@ var testFlagDefn = []*testFlagSpec{
// Unfortunately for us, we need to do our own flag processing because go test // Unfortunately for us, we need to do our own flag processing because go test
// grabs some flags but otherwise its command line is just a holding place for // grabs some flags but otherwise its command line is just a holding place for
// test.out's arguments. // test.out's arguments.
func testFlags(args []string) (passToTest []string) { // We allow known flags both before and after the package name list,
// to allow both
// go test fmt -custom-flag-for-fmt-test
// go test -x math
func testFlags(args []string) (packageNames, passToTest []string) {
inPkg := false
for i := 0; i < len(args); i++ { for i := 0; i < len(args); i++ {
if !strings.HasPrefix(args[i], "-") {
if !inPkg && packageNames == nil {
// First package name we've seen.
inPkg = true
}
if inPkg {
packageNames = append(packageNames, args[i])
continue
}
}
if inPkg {
// Found an argument beginning with "-"; end of package list.
inPkg = false
}
f, value, extraWord := testFlag(args, i) f, value, extraWord := testFlag(args, i)
if f == nil { if f == nil {
// This is a flag we do not know; we must assume
// that any args we see after this might be flag
// arguments, not package names.
inPkg = false
if packageNames == nil {
// make non-nil: we have seen the empty package list
packageNames = []string{}
}
passToTest = append(passToTest, args[i]) passToTest = append(passToTest, args[i])
continue continue
} }
@ -90,6 +119,8 @@ func testFlags(args []string) (passToTest []string) {
setBoolFlag(&testC, value) setBoolFlag(&testC, value)
case "x": case "x":
setBoolFlag(&testX, value) setBoolFlag(&testX, value)
case "v":
setBoolFlag(&testV, value)
case "file": case "file":
testFiles = append(testFiles, value) testFiles = append(testFiles, value)
} }