go/ssa: remove deprecated FindTests and CreateTestMainPackage
For golang/go#48547
Change-Id: I1337b99c90ce81b58dfaa93e49c6dcb884330b22
Reviewed-on: https://go-review.googlesource.com/c/tools/+/363659
Run-TryBot: Zvonimir Pavlinovic <zpavlinovic@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
Trust: Zvonimir Pavlinovic <zpavlinovic@google.com>
diff --git a/go/ssa/testmain.go b/go/ssa/testmain.go
deleted file mode 100644
index b748332..0000000
--- a/go/ssa/testmain.go
+++ /dev/null
@@ -1,277 +0,0 @@
-// 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.
-
-package ssa
-
-// CreateTestMainPackage synthesizes a main package that runs all the
-// tests of the supplied packages.
-// It is closely coupled to $GOROOT/src/cmd/go/test.go and $GOROOT/src/testing.
-//
-// TODO(adonovan): throws this all away now that x/tools/go/packages
-// provides access to the actual synthetic test main files.
-
-import (
- "bytes"
- "fmt"
- "go/ast"
- "go/parser"
- "go/types"
- "log"
- "os"
- "strings"
- "text/template"
-
- "golang.org/x/tools/internal/typeparams"
-)
-
-// FindTests returns the Test, Benchmark, and Example functions
-// (as defined by "go test") defined in the specified package,
-// and its TestMain function, if any.
-//
-// Deprecated: Use golang.org/x/tools/go/packages to access synthetic
-// testmain packages.
-func FindTests(pkg *Package) (tests, benchmarks, examples []*Function, main *Function) {
- prog := pkg.Prog
-
- // The first two of these may be nil: if the program doesn't import "testing",
- // it can't contain any tests, but it may yet contain Examples.
- var testSig *types.Signature // func(*testing.T)
- var benchmarkSig *types.Signature // func(*testing.B)
- var exampleSig = types.NewSignature(nil, nil, nil, false) // func()
-
- // Obtain the types from the parameters of testing.MainStart.
- if testingPkg := prog.ImportedPackage("testing"); testingPkg != nil {
- mainStart := testingPkg.Func("MainStart")
- params := mainStart.Signature.Params()
- testSig = funcField(params.At(1).Type())
- benchmarkSig = funcField(params.At(2).Type())
-
- // Does the package define this function?
- // func TestMain(*testing.M)
- if f := pkg.Func("TestMain"); f != nil {
- sig := f.Type().(*types.Signature)
- starM := mainStart.Signature.Results().At(0).Type() // *testing.M
- if sig.Results().Len() == 0 &&
- sig.Params().Len() == 1 &&
- types.Identical(sig.Params().At(0).Type(), starM) {
- main = f
- }
- }
- }
-
- // TODO(adonovan): use a stable order, e.g. lexical.
- for _, mem := range pkg.Members {
- if f, ok := mem.(*Function); ok &&
- ast.IsExported(f.Name()) &&
- strings.HasSuffix(prog.Fset.Position(f.Pos()).Filename, "_test.go") {
-
- switch {
- case testSig != nil && isTestSig(f, "Test", testSig):
- tests = append(tests, f)
- case benchmarkSig != nil && isTestSig(f, "Benchmark", benchmarkSig):
- benchmarks = append(benchmarks, f)
- case isTestSig(f, "Example", exampleSig):
- examples = append(examples, f)
- default:
- continue
- }
- }
- }
- return
-}
-
-// Like isTest, but checks the signature too.
-func isTestSig(f *Function, prefix string, sig *types.Signature) bool {
- return isTest(f.Name(), prefix) && types.Identical(f.Signature, sig)
-}
-
-// Given the type of one of the three slice parameters of testing.Main,
-// returns the function type.
-func funcField(slice types.Type) *types.Signature {
- return slice.(*types.Slice).Elem().Underlying().(*types.Struct).Field(1).Type().(*types.Signature)
-}
-
-// isTest tells whether name looks like a test (or benchmark, according to prefix).
-// It is a Test (say) if there is a character after Test that is not a lower-case letter.
-// We don't want TesticularCancer.
-// Plundered from $GOROOT/src/cmd/go/test.go
-func isTest(name, prefix string) bool {
- if !strings.HasPrefix(name, prefix) {
- return false
- }
- if len(name) == len(prefix) { // "Test" is ok
- return true
- }
- return ast.IsExported(name[len(prefix):])
-}
-
-// CreateTestMainPackage creates and returns a synthetic "testmain"
-// package for the specified package if it defines tests, benchmarks or
-// executable examples, or nil otherwise. The new package is named
-// "main" and provides a function named "main" that runs the tests,
-// similar to the one that would be created by the 'go test' tool.
-//
-// Subsequent calls to prog.AllPackages include the new package.
-// The package pkg must belong to the program prog.
-//
-// Deprecated: Use golang.org/x/tools/go/packages to access synthetic
-// testmain packages.
-func (prog *Program) CreateTestMainPackage(pkg *Package) *Package {
- if pkg.Prog != prog {
- log.Fatal("Package does not belong to Program")
- }
-
- // Template data
- var data struct {
- Pkg *Package
- Tests, Benchmarks, Examples []*Function
- Main *Function
- Go18 bool
- }
- data.Pkg = pkg
-
- // Enumerate tests.
- data.Tests, data.Benchmarks, data.Examples, data.Main = FindTests(pkg)
- if data.Main == nil &&
- data.Tests == nil && data.Benchmarks == nil && data.Examples == nil {
- return nil
- }
-
- // Synthesize source for testmain package.
- path := pkg.Pkg.Path() + "$testmain"
- tmpl := testmainTmpl
- if testingPkg := prog.ImportedPackage("testing"); testingPkg != nil {
- // In Go 1.8, testing.MainStart's first argument is an interface, not a func.
- data.Go18 = types.IsInterface(testingPkg.Func("MainStart").Signature.Params().At(0).Type())
- } else {
- // The program does not import "testing", but FindTests
- // returned non-nil, which must mean there were Examples
- // but no Test, Benchmark, or TestMain functions.
-
- // We'll simply call them from testmain.main; this will
- // ensure they don't panic, but will not check any
- // "Output:" comments.
- // (We should not execute an Example that has no
- // "Output:" comment, but it's impossible to tell here.)
- tmpl = examplesOnlyTmpl
- }
- var buf bytes.Buffer
- if err := tmpl.Execute(&buf, data); err != nil {
- log.Fatalf("internal error expanding template for %s: %v", path, err)
- }
- if false { // debugging
- fmt.Fprintln(os.Stderr, buf.String())
- }
-
- // Parse and type-check the testmain package.
- f, err := parser.ParseFile(prog.Fset, path+".go", &buf, parser.Mode(0))
- if err != nil {
- log.Fatalf("internal error parsing %s: %v", path, err)
- }
- conf := types.Config{
- DisableUnusedImportCheck: true,
- Importer: importer{pkg},
- }
- files := []*ast.File{f}
- info := &types.Info{
- Types: make(map[ast.Expr]types.TypeAndValue),
- Defs: make(map[*ast.Ident]types.Object),
- Uses: make(map[*ast.Ident]types.Object),
- Implicits: make(map[ast.Node]types.Object),
- Scopes: make(map[ast.Node]*types.Scope),
- Selections: make(map[*ast.SelectorExpr]*types.Selection),
- }
- typeparams.InitInstanceInfo(info)
- testmainPkg, err := conf.Check(path, prog.Fset, files, info)
- if err != nil {
- log.Fatalf("internal error type-checking %s: %v", path, err)
- }
-
- // Create and build SSA code.
- testmain := prog.CreatePackage(testmainPkg, files, info, false)
- testmain.SetDebugMode(false)
- testmain.Build()
- testmain.Func("main").Synthetic = "test main function"
- testmain.Func("init").Synthetic = "package initializer"
- return testmain
-}
-
-// An implementation of types.Importer for an already loaded SSA program.
-type importer struct {
- pkg *Package // package under test; may be non-importable
-}
-
-func (imp importer) Import(path string) (*types.Package, error) {
- if p := imp.pkg.Prog.ImportedPackage(path); p != nil {
- return p.Pkg, nil
- }
- if path == imp.pkg.Pkg.Path() {
- return imp.pkg.Pkg, nil
- }
- return nil, fmt.Errorf("not found") // can't happen
-}
-
-var testmainTmpl = template.Must(template.New("testmain").Parse(`
-package main
-
-import "io"
-import "os"
-import "testing"
-import p {{printf "%q" .Pkg.Pkg.Path}}
-
-{{if .Go18}}
-type deps struct{}
-
-func (deps) ImportPath() string { return "" }
-func (deps) MatchString(pat, str string) (bool, error) { return true, nil }
-func (deps) SetPanicOnExit0(bool) {}
-func (deps) StartCPUProfile(io.Writer) error { return nil }
-func (deps) StartTestLog(io.Writer) {}
-func (deps) StopCPUProfile() {}
-func (deps) StopTestLog() error { return nil }
-func (deps) WriteHeapProfile(io.Writer) error { return nil }
-func (deps) WriteProfileTo(string, io.Writer, int) error { return nil }
-
-var match deps
-{{else}}
-func match(_, _ string) (bool, error) { return true, nil }
-{{end}}
-
-func main() {
- tests := []testing.InternalTest{
-{{range .Tests}}
- { {{printf "%q" .Name}}, p.{{.Name}} },
-{{end}}
- }
- benchmarks := []testing.InternalBenchmark{
-{{range .Benchmarks}}
- { {{printf "%q" .Name}}, p.{{.Name}} },
-{{end}}
- }
- examples := []testing.InternalExample{
-{{range .Examples}}
- {Name: {{printf "%q" .Name}}, F: p.{{.Name}}},
-{{end}}
- }
- m := testing.MainStart(match, tests, benchmarks, examples)
-{{with .Main}}
- p.{{.Name}}(m)
-{{else}}
- os.Exit(m.Run())
-{{end}}
-}
-
-`))
-
-var examplesOnlyTmpl = template.Must(template.New("examples").Parse(`
-package main
-
-import p {{printf "%q" .Pkg.Pkg.Path}}
-
-func main() {
-{{range .Examples}}
- p.{{.Name}}()
-{{end}}
-}
-`))
diff --git a/go/ssa/testmain_test.go b/go/ssa/testmain_test.go
deleted file mode 100644
index e24b23b..0000000
--- a/go/ssa/testmain_test.go
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2014 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.
-
-package ssa_test
-
-// Tests of FindTests. CreateTestMainPackage is tested via the interpreter.
-// TODO(adonovan): test the 'pkgs' result from FindTests.
-
-import (
- "fmt"
- "sort"
- "testing"
-
- "golang.org/x/tools/go/loader"
- "golang.org/x/tools/go/ssa"
- "golang.org/x/tools/go/ssa/ssautil"
-)
-
-func create(t *testing.T, content string) *ssa.Package {
- var conf loader.Config
- f, err := conf.ParseFile("foo_test.go", content)
- if err != nil {
- t.Fatal(err)
- }
- conf.CreateFromFiles("foo", f)
-
- lprog, err := conf.Load()
- if err != nil {
- t.Fatal(err)
- }
-
- // We needn't call Build.
- foo := lprog.Package("foo").Pkg
- return ssautil.CreateProgram(lprog, ssa.SanityCheckFunctions).Package(foo)
-}
-
-func TestFindTests(t *testing.T) {
- test := `
-package foo
-
-import "testing"
-
-type T int
-
-// Tests:
-func Test(t *testing.T) {}
-func TestA(t *testing.T) {}
-func TestB(t *testing.T) {}
-
-// Not tests:
-func testC(t *testing.T) {}
-func TestD() {}
-func testE(t *testing.T) int { return 0 }
-func (T) Test(t *testing.T) {}
-
-// Benchmarks:
-func Benchmark(*testing.B) {}
-func BenchmarkA(b *testing.B) {}
-func BenchmarkB(*testing.B) {}
-
-// Not benchmarks:
-func benchmarkC(t *testing.T) {}
-func BenchmarkD() {}
-func benchmarkE(t *testing.T) int { return 0 }
-func (T) Benchmark(t *testing.T) {}
-
-// Examples:
-func Example() {}
-func ExampleA() {}
-
-// Not examples:
-func exampleC() {}
-func ExampleD(t *testing.T) {}
-func exampleE() int { return 0 }
-func (T) Example() {}
-`
- pkg := create(t, test)
- tests, benchmarks, examples, _ := ssa.FindTests(pkg)
-
- sort.Sort(funcsByPos(tests))
- if got, want := fmt.Sprint(tests), "[foo.Test foo.TestA foo.TestB]"; got != want {
- t.Errorf("FindTests.tests = %s, want %s", got, want)
- }
-
- sort.Sort(funcsByPos(benchmarks))
- if got, want := fmt.Sprint(benchmarks), "[foo.Benchmark foo.BenchmarkA foo.BenchmarkB]"; got != want {
- t.Errorf("FindTests.benchmarks = %s, want %s", got, want)
- }
-
- sort.Sort(funcsByPos(examples))
- if got, want := fmt.Sprint(examples), "[foo.Example foo.ExampleA]"; got != want {
- t.Errorf("FindTests examples = %s, want %s", got, want)
- }
-}
-
-func TestFindTestsTesting(t *testing.T) {
- test := `
-package foo
-
-// foo does not import "testing", but defines Examples.
-
-func Example() {}
-func ExampleA() {}
-`
- pkg := create(t, test)
- tests, benchmarks, examples, _ := ssa.FindTests(pkg)
- if len(tests) > 0 {
- t.Errorf("FindTests.tests = %s, want none", tests)
- }
- if len(benchmarks) > 0 {
- t.Errorf("FindTests.benchmarks = %s, want none", benchmarks)
- }
- sort.Sort(funcsByPos(examples))
- if got, want := fmt.Sprint(examples), "[foo.Example foo.ExampleA]"; got != want {
- t.Errorf("FindTests examples = %s, want %s", got, want)
- }
-}
-
-type funcsByPos []*ssa.Function
-
-func (p funcsByPos) Len() int { return len(p) }
-func (p funcsByPos) Less(i, j int) bool { return p[i].Pos() < p[j].Pos() }
-func (p funcsByPos) Swap(i, j int) { p[i], p[j] = p[j], p[i] }