mirror of
https://github.com/golang/go
synced 2024-11-18 18:14:43 -07:00
go/packages: add Option.Tests bool, which affects pattern expansion
In the go build system, test packages and executables do not have a name distinct from the package under test; they are implied, so "go test fmt" means build those packages but "go build fmt" does not. This change adds a Tests boolean option to indicate that implied tests are desired during pattern expansion. It has no effect on build systems that have explicit names for tests, such as Blaze/Bazel. The gopackages diagnostic tool now has a -test flag. Change-Id: I424f343958c4286539e518d5f30067da19a57f3b Reviewed-on: https://go-review.googlesource.com/123775 Reviewed-by: Michael Matloob <matloob@golang.org>
This commit is contained in:
parent
9d3ae49c73
commit
18e9dfbf20
@ -25,7 +25,7 @@ type GoTooOldError struct{ error }
|
||||
|
||||
// golistPackages uses the "go list" command to expand the
|
||||
// pattern words and return metadata for the specified packages.
|
||||
func golistPackages(ctx context.Context, gopath string, cgo, export bool, words []string) ([]*Package, error) {
|
||||
func golistPackages(ctx context.Context, gopath string, cgo, export, tests bool, words []string) ([]*Package, error) {
|
||||
// Fields must match go list;
|
||||
// see $GOROOT/src/cmd/go/internal/load/pkg.go.
|
||||
type jsonPackage struct {
|
||||
@ -62,7 +62,7 @@ func golistPackages(ctx context.Context, gopath string, cgo, export bool, words
|
||||
// Run "go list" for complete
|
||||
// information on the specified packages.
|
||||
|
||||
buf, err := golist(ctx, gopath, cgo, export, words)
|
||||
buf, err := golist(ctx, gopath, cgo, export, tests, words)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -176,19 +176,13 @@ func absJoin(dir string, fileses ...[]string) (res []string) {
|
||||
}
|
||||
|
||||
// golist returns the JSON-encoded result of a "go list args..." query.
|
||||
func golist(ctx context.Context, gopath string, cgo, export bool, args []string) (*bytes.Buffer, error) {
|
||||
func golist(ctx context.Context, gopath string, cgo, export, tests bool, args []string) (*bytes.Buffer, error) {
|
||||
out := new(bytes.Buffer)
|
||||
if len(args) == 0 {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
const test = true // TODO(adonovan): expose a flag for this.
|
||||
|
||||
cmd := exec.CommandContext(ctx, "go", append([]string{
|
||||
"list",
|
||||
"-e",
|
||||
fmt.Sprintf("-cgo=%t", cgo),
|
||||
fmt.Sprintf("-test=%t", test),
|
||||
fmt.Sprintf("-test=%t", tests),
|
||||
fmt.Sprintf("-export=%t", export),
|
||||
"-deps",
|
||||
"-json",
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
// flags
|
||||
var (
|
||||
depsFlag = flag.Bool("deps", false, "show dependencies too")
|
||||
testFlag = flag.Bool("test", false, "include any tests implied by the patterns")
|
||||
cgoFlag = flag.Bool("cgo", true, "process cgo files")
|
||||
mode = flag.String("mode", "metadata", "mode (one of metadata, typecheck, wholeprogram)")
|
||||
private = flag.Bool("private", false, "show non-exported declarations too")
|
||||
@ -119,6 +120,7 @@ func main() {
|
||||
opts := &packages.Options{
|
||||
Error: func(error) {}, // we'll take responsibility for printing errors
|
||||
DisableCgo: !*cgoFlag,
|
||||
Tests: *testFlag,
|
||||
}
|
||||
lpkgs, err := load(opts, flag.Args()...)
|
||||
if err != nil {
|
||||
|
@ -40,6 +40,19 @@ type Options struct {
|
||||
// Replace with flags/cwd/environ pass-through.
|
||||
GOPATH string
|
||||
|
||||
// The Tests flag causes the result to include any test packages
|
||||
// implied by the patterns.
|
||||
//
|
||||
// For example, under 'go build', the "fmt" pattern ordinarily
|
||||
// identifies a single importable package, but with the Tests
|
||||
// flag it additionally denotes the "fmt.test" executable, which
|
||||
// in turn depends on the variant of "fmt" augmented by its
|
||||
// in-packages tests, and the "fmt_test" external test package.
|
||||
//
|
||||
// For build systems in which test names are explicit,
|
||||
// this flag may have no effect.
|
||||
Tests bool
|
||||
|
||||
// DisableCgo disables cgo-processing of files that import "C",
|
||||
// and removes the 'cgo' build tag, which may affect source file selection.
|
||||
// By default, TypeCheck, and WholeProgram queries process such
|
||||
@ -298,9 +311,13 @@ func (ld *loader) load(patterns ...string) ([]*Package, error) {
|
||||
ld.GOPATH = os.Getenv("GOPATH")
|
||||
}
|
||||
|
||||
if len(patterns) == 0 {
|
||||
return nil, fmt.Errorf("no packages to load")
|
||||
}
|
||||
|
||||
// Do the metadata query and partial build.
|
||||
// TODO(adonovan): support alternative build systems at this seam.
|
||||
list, err := golistPackages(ld.Context, ld.GOPATH, ld.cgo, ld.mode == typeCheck, patterns)
|
||||
list, err := golistPackages(ld.Context, ld.GOPATH, ld.cgo, ld.mode == typeCheck, ld.Tests, patterns)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -320,7 +337,7 @@ func (ld *loader) load(patterns ...string) ([]*Package, error) {
|
||||
}
|
||||
}
|
||||
if len(pkgs) == 0 {
|
||||
return nil, fmt.Errorf("no packages to load")
|
||||
return nil, fmt.Errorf("packages not found")
|
||||
}
|
||||
|
||||
// Materialize the import graph.
|
||||
|
@ -36,7 +36,6 @@ import (
|
||||
// import error) will result in a JSON blob with no name and a
|
||||
// nonexistent testmain file in GoFiles. Test that we handle this
|
||||
// gracefully.
|
||||
// - import graph for synthetic testmain and "p [t.test]" packages.
|
||||
// - IsTest boolean
|
||||
//
|
||||
// TypeCheck & WholeProgram modes:
|
||||
@ -44,6 +43,7 @@ import (
|
||||
// - Packages.Info is correctly set.
|
||||
// - typechecker configuration is honored
|
||||
// - import cycles are gracefully handled in type checker.
|
||||
// - test typechecking of generated test main and cgo.
|
||||
|
||||
func TestMetadataImportGraph(t *testing.T) {
|
||||
tmp, cleanup := enterTree(t, map[string]string{
|
||||
@ -74,6 +74,34 @@ func TestMetadataImportGraph(t *testing.T) {
|
||||
a
|
||||
b
|
||||
* c
|
||||
* e
|
||||
errors
|
||||
* subdir/d
|
||||
unsafe
|
||||
b -> a
|
||||
b -> errors
|
||||
c -> b
|
||||
c -> unsafe
|
||||
e -> b
|
||||
e -> c
|
||||
`[1:]
|
||||
|
||||
if graph != wantGraph {
|
||||
t.Errorf("wrong import graph: got <<%s>>, want <<%s>>", graph, wantGraph)
|
||||
}
|
||||
|
||||
opts.Tests = true
|
||||
initial, err = packages.Metadata(opts, "c", "subdir/d", "e")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Check graph topology.
|
||||
graph, all = importGraph(initial)
|
||||
wantGraph = `
|
||||
a
|
||||
b
|
||||
* c
|
||||
* e
|
||||
errors
|
||||
math/bits
|
||||
@ -114,7 +142,7 @@ func TestMetadataImportGraph(t *testing.T) {
|
||||
{"e", "main", "command", "e.go e2.go"},
|
||||
{"errors", "errors", "package", "errors.go"},
|
||||
{"subdir/d", "d", "package", "d.go"},
|
||||
// {"subdir/d.test", "main", "test command", "<hideous generated file name>"},
|
||||
{"subdir/d.test", "main", "test command", "0.go"},
|
||||
{"unsafe", "unsafe", "package", ""},
|
||||
} {
|
||||
p, ok := all[test.id]
|
||||
@ -489,8 +517,13 @@ func errorMessages(errors []error) []string {
|
||||
func srcs(p *packages.Package) (basenames []string) {
|
||||
// Ideally we would show the root-relative portion (e.g. after
|
||||
// src/) but vgo doesn't necessarily have a src/ dir.
|
||||
for _, src := range p.Srcs {
|
||||
basenames = append(basenames, filepath.Base(src))
|
||||
for i, src := range p.Srcs {
|
||||
if strings.Contains(src, ".cache/go-build") {
|
||||
src = fmt.Sprintf("%d.go", i) // make cache names predictable
|
||||
} else {
|
||||
src = filepath.Base(src)
|
||||
}
|
||||
basenames = append(basenames, src)
|
||||
}
|
||||
return basenames
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ func TestStdlibMetadata(t *testing.T) {
|
||||
|
||||
t.Logf("Loaded %d packages", len(pkgs))
|
||||
numPkgs := len(pkgs)
|
||||
if want := 340; numPkgs < want {
|
||||
if want := 186; numPkgs < want {
|
||||
t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user