From: Robert Griesemer Date: Tue, 5 Mar 2013 19:42:43 +0000 (-0800) Subject: go/types: add test typechecking std lib X-Git-Tag: go1.1rc2~684 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=d01516796c94f6c4da58bbc2f8c010e3f48ef220;p=gostls13.git go/types: add test typechecking std lib - run time is limited if -short is set - also added missing TODO to unrelated file return.go R=r CC=golang-dev https://golang.org/cl/7448052 --- diff --git a/src/pkg/go/types/return.go b/src/pkg/go/types/return.go index 5806fb25da..8644d28c91 100644 --- a/src/pkg/go/types/return.go +++ b/src/pkg/go/types/return.go @@ -81,7 +81,6 @@ func (check *checker) isTerminating(s ast.Stmt, label string) bool { if s.Cond == nil && !hasBreak(s.Body, label, true) { return true } - } return false @@ -106,6 +105,10 @@ func (check *checker) isTerminatingSwitch(body *ast.BlockStmt, label string) boo return hasDefault } +// TODO(gri) For nested breakable statements, the current implementation of hasBreak +// will traverse the same subtree repeatedly, once for each label. Replace +// with a single-pass label/break matching phase. + // hasBreak reports if s is or contains a break statement // referring to the label-ed statement or implicit-ly the // closest outer breakable statement. diff --git a/src/pkg/go/types/stdlib_test.go b/src/pkg/go/types/stdlib_test.go new file mode 100644 index 0000000000..8b264119d5 --- /dev/null +++ b/src/pkg/go/types/stdlib_test.go @@ -0,0 +1,133 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file tests types.Check by using it to +// typecheck the standard library. + +package types + +import ( + "flag" + "fmt" + "go/ast" + "go/build" + "go/parser" + "go/scanner" + "go/token" + "io/ioutil" + "path/filepath" + "runtime" + "testing" + "time" +) + +var verbose = flag.Bool("types.v", false, "verbose mode") + +var ( + pkgCount int // number of packages processed + start = time.Now() +) + +func TestStdlib(t *testing.T) { + walkDirs(t, filepath.Join(runtime.GOROOT(), "src/pkg")) + if *verbose { + fmt.Println(pkgCount, "packages typechecked in", time.Since(start)) + } +} + +// Package paths of excluded packages. +var excluded = map[string]bool{ + "builtin": true, +} + +// typecheck typechecks the given package files. +func typecheck(t *testing.T, filenames []string) { + fset := token.NewFileSet() + + // parse package files + var files []*ast.File + for _, filename := range filenames { + file, err := parser.ParseFile(fset, filename, nil, parser.DeclarationErrors|parser.AllErrors) + if err != nil { + // the parser error may be a list of individual errors; report them all + if list, ok := err.(scanner.ErrorList); ok { + for _, err := range list { + t.Error(err) + } + return + } + t.Error(err) + return + } + + if *verbose { + if len(files) == 0 { + fmt.Println("package", file.Name.Name) + } + fmt.Println("\t", filename) + } + + files = append(files, file) + } + + // typecheck package files + ctxt := Context{ + Error: func(err error) { t.Error(err) }, + } + ctxt.Check(fset, files) + pkgCount++ +} + +// pkgfiles returns the list of package files for the given directory. +func pkgfiles(t *testing.T, dir string) []string { + ctxt := build.Default + ctxt.CgoEnabled = false + pkg, err := ctxt.ImportDir(dir, 0) + if err != nil { + if _, nogo := err.(*build.NoGoError); !nogo { + t.Error(err) + } + return nil + } + if excluded[pkg.ImportPath] { + return nil + } + var filenames []string + for _, name := range pkg.GoFiles { + filenames = append(filenames, filepath.Join(pkg.Dir, name)) + } + for _, name := range pkg.TestGoFiles { + filenames = append(filenames, filepath.Join(pkg.Dir, name)) + } + return filenames +} + +// Note: Could use filepath.Walk instead of walkDirs but that wouldn't +// necessarily be shorter or clearer after adding the code to +// terminate early for -short tests. + +func walkDirs(t *testing.T, dir string) { + // limit run time for short tests + if testing.Short() && time.Since(start) >= 750*time.Millisecond { + return + } + + fis, err := ioutil.ReadDir(dir) + if err != nil { + t.Error(err) + return + } + + // typecheck package in directory + if files := pkgfiles(t, dir); files != nil { + typecheck(t, files) + } + + // traverse subdirectories, but don't walk into testdata + for _, fi := range fis { + if fi.IsDir() && fi.Name() != "testdata" { + walkDirs(t, filepath.Join(dir, fi.Name())) + } + } +}