зеркало из https://github.com/golang/tools.git
merge two test cases and check possible errors
This commit is contained in:
Родитель
deda7b7b00
Коммит
a859e27d81
|
@ -27,27 +27,52 @@ import (
|
|||
"golang.org/x/tools/txtar"
|
||||
)
|
||||
|
||||
// TestRTASingleFile runs RTA on each testdata/*.txtar file containing a single
|
||||
// go file and compares the results with the expectations expressed in the WANT
|
||||
// TestRTA runs RTA on each testdata/*.txtar file containing a single
|
||||
// go file in a single package or multiple files in different packages,
|
||||
// and compares the results with the expectations expressed in the WANT
|
||||
// comment.
|
||||
func TestRTASingleFile(t *testing.T) {
|
||||
func TestRTA(t *testing.T) {
|
||||
archivePaths := []string{
|
||||
"testdata/func.txtar",
|
||||
"testdata/pkgmaingenerics.txtar",
|
||||
"testdata/generics.txtar",
|
||||
"testdata/iface.txtar",
|
||||
"testdata/reflectcall.txtar",
|
||||
"testdata/rtype.txtar",
|
||||
"testdata/multipkgs.txtar",
|
||||
}
|
||||
for _, archive := range archivePaths {
|
||||
t.Run(archive, func(t *testing.T) {
|
||||
pkgs := loadPackages(t, archive)
|
||||
|
||||
f := pkgs[0].Syntax[0]
|
||||
// find the file which contains the expected result
|
||||
var f *ast.File
|
||||
for _, p := range pkgs {
|
||||
// We assume the packages have a single file or
|
||||
// the wanted result is in the first file of the main package.
|
||||
if p.Name == "main" {
|
||||
f = p.Syntax[0]
|
||||
}
|
||||
}
|
||||
if f == nil {
|
||||
t.Fatalf("failed to find the file with expected result within main package %s", archive)
|
||||
}
|
||||
|
||||
prog, spkgs := ssautil.Packages(pkgs, ssa.SanityCheckFunctions|ssa.InstantiateGenerics)
|
||||
|
||||
// find the main package to get functions for rta analysis
|
||||
var mainPkg *ssa.Package
|
||||
for _, sp := range spkgs {
|
||||
if sp.Pkg.Name() == "main" {
|
||||
mainPkg = sp
|
||||
break
|
||||
}
|
||||
}
|
||||
if mainPkg == nil {
|
||||
t.Fatalf("failed to find main ssa package %s", archive)
|
||||
}
|
||||
|
||||
prog, spkg := ssautil.Packages(pkgs, ssa.SanityCheckFunctions|ssa.InstantiateGenerics)
|
||||
prog.Build()
|
||||
mainPkg := spkg[0]
|
||||
|
||||
res := rta.Analyze([]*ssa.Function{
|
||||
mainPkg.Func("main"),
|
||||
mainPkg.Func("init"),
|
||||
|
@ -58,38 +83,6 @@ func TestRTASingleFile(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestRTAOnPackages runs RTA on a go module which contains multiple packages to test the case
|
||||
// when an interface has implementations across different packages.
|
||||
func TestRTAOnPackages(t *testing.T) {
|
||||
pkgs := loadPackages(t, "testdata/multipkgs.txtar")
|
||||
|
||||
var f *ast.File
|
||||
for _, p := range pkgs {
|
||||
// We assume the packages have a single file or
|
||||
// the wanted result is in the first file of the main package.
|
||||
if p.Name == "main" {
|
||||
f = p.Syntax[0]
|
||||
}
|
||||
}
|
||||
|
||||
prog, spkgs := ssautil.Packages(pkgs, ssa.SanityCheckFunctions|ssa.InstantiateGenerics)
|
||||
prog.Build()
|
||||
var mainPkg *ssa.Package
|
||||
for _, sp := range spkgs {
|
||||
if sp.Pkg.Name() == "main" {
|
||||
mainPkg = sp
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
res := rta.Analyze([]*ssa.Function{
|
||||
mainPkg.Func("main"),
|
||||
mainPkg.Func("init"),
|
||||
}, true)
|
||||
|
||||
check(t, f, mainPkg, res)
|
||||
}
|
||||
|
||||
// loadPackages unpacks the archive to a temporary directory and loads all packages within it.
|
||||
func loadPackages(t *testing.T, archive string) []*packages.Package {
|
||||
ar, err := txtar.ParseFile(archive)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
-- go.mod --
|
||||
module example.com/generic
|
||||
module example.com
|
||||
go 1.18
|
||||
|
||||
-- generics.go --
|
||||
package generic
|
||||
package main
|
||||
|
||||
// Test of generic function calls.
|
||||
|
||||
|
@ -51,34 +51,31 @@ func lambda[X I]() func() func() {
|
|||
}
|
||||
}
|
||||
|
||||
// Note: example.com/generic is used here as we load a single file by packages.Load,
|
||||
// it will use example.com/generic instead of the package name for ImportedPath
|
||||
|
||||
// WANT:
|
||||
//
|
||||
// edge (*C).Foo --static method call--> (C).Foo
|
||||
// edge (A).Foo$bound --static method call--> (A).Foo
|
||||
// edge instantiated[example.com/generic.A] --static method call--> (A).Foo
|
||||
// edge instantiated[example.com/generic.B] --static method call--> (B).Foo
|
||||
// edge instantiated[example.com.A] --static method call--> (A).Foo
|
||||
// edge instantiated[example.com.B] --static method call--> (B).Foo
|
||||
// edge main --dynamic method call--> (*C).Foo
|
||||
// edge main --dynamic function call--> (A).Foo$bound
|
||||
// edge main --dynamic method call--> (C).Foo
|
||||
// edge main --static function call--> instantiated[example.com/generic.A]
|
||||
// edge main --static function call--> instantiated[example.com/generic.B]
|
||||
// edge main --static function call--> lambda[example.com/generic.A]
|
||||
// edge main --dynamic function call--> lambda[example.com/generic.A]$1
|
||||
// edge main --static function call--> local[example.com/generic.C]
|
||||
// edge main --static function call--> instantiated[example.com.A]
|
||||
// edge main --static function call--> instantiated[example.com.B]
|
||||
// edge main --static function call--> lambda[example.com.A]
|
||||
// edge main --dynamic function call--> lambda[example.com.A]$1
|
||||
// edge main --static function call--> local[example.com.C]
|
||||
//
|
||||
// reachable (*C).Foo
|
||||
// reachable (A).Foo
|
||||
// reachable (A).Foo$bound
|
||||
// reachable (B).Foo
|
||||
// reachable (C).Foo
|
||||
// reachable instantiated[example.com/generic.A]
|
||||
// reachable instantiated[example.com/generic.B]
|
||||
// reachable lambda[example.com/generic.A]
|
||||
// reachable lambda[example.com/generic.A]$1
|
||||
// reachable local[example.com/generic.C]
|
||||
// reachable instantiated[example.com.A]
|
||||
// reachable instantiated[example.com.B]
|
||||
// reachable lambda[example.com.A]
|
||||
// reachable lambda[example.com.A]$1
|
||||
// reachable local[example.com.C]
|
||||
//
|
||||
// rtype *C
|
||||
// rtype C
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
-- go.mod --
|
||||
module example.com
|
||||
go 1.18
|
||||
|
||||
-- generics.go --
|
||||
package main
|
||||
|
||||
// Test of generic function calls.
|
||||
|
||||
type I interface {
|
||||
Foo()
|
||||
}
|
||||
|
||||
type A struct{}
|
||||
|
||||
func (a A) Foo() {}
|
||||
|
||||
type B struct{}
|
||||
|
||||
func (b B) Foo() {}
|
||||
|
||||
func instantiated[X I](x X) {
|
||||
x.Foo()
|
||||
}
|
||||
|
||||
var a A
|
||||
var b B
|
||||
|
||||
func main() {
|
||||
instantiated[A](a) // static call
|
||||
instantiated[B](b) // static call
|
||||
|
||||
local[C]().Foo()
|
||||
|
||||
lambda[A]()()()
|
||||
}
|
||||
|
||||
func local[X I]() I {
|
||||
var x X
|
||||
return x
|
||||
}
|
||||
|
||||
type C struct{}
|
||||
|
||||
func (c C) Foo() {}
|
||||
|
||||
func lambda[X I]() func() func() {
|
||||
return func() func() {
|
||||
var x X
|
||||
return x.Foo
|
||||
}
|
||||
}
|
||||
|
||||
// Note: example.com is used here as we load a single file by packages.Load,
|
||||
// it will use example.com instead of the package name for ImportedPath
|
||||
|
||||
// WANT:
|
||||
//
|
||||
// edge (*C).Foo --static method call--> (C).Foo
|
||||
// edge (A).Foo$bound --static method call--> (A).Foo
|
||||
// edge instantiated[example.com.A] --static method call--> (A).Foo
|
||||
// edge instantiated[example.com.B] --static method call--> (B).Foo
|
||||
// edge main --dynamic method call--> (*C).Foo
|
||||
// edge main --dynamic function call--> (A).Foo$bound
|
||||
// edge main --dynamic method call--> (C).Foo
|
||||
// edge main --static function call--> instantiated[example.com.A]
|
||||
// edge main --static function call--> instantiated[example.com.B]
|
||||
// edge main --static function call--> lambda[example.com.A]
|
||||
// edge main --dynamic function call--> lambda[example.com.A]$1
|
||||
// edge main --static function call--> local[example.com.C]
|
||||
//
|
||||
// reachable (*C).Foo
|
||||
// reachable (A).Foo
|
||||
// reachable (A).Foo$bound
|
||||
// reachable (B).Foo
|
||||
// reachable (C).Foo
|
||||
// reachable instantiated[example.com.A]
|
||||
// reachable instantiated[example.com.B]
|
||||
// reachable lambda[example.com.A]
|
||||
// reachable lambda[example.com.A]$1
|
||||
// reachable local[example.com.C]
|
||||
//
|
||||
// rtype *C
|
||||
// rtype C
|
Загрузка…
Ссылка в новой задаче