diff --git a/go/internal/gcimporter/gcimporter11_test.go b/go/internal/gcimporter/gcimporter11_test.go new file mode 100644 index 00000000..787620d6 --- /dev/null +++ b/go/internal/gcimporter/gcimporter11_test.go @@ -0,0 +1,134 @@ +// Copyright 2018 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. + +// +build go1.11 + +package gcimporter + +import ( + "go/types" + "os" + "runtime" + "strings" + "testing" +) + +var importedObjectTests = []struct { + name string + want string +}{ + // non-interfaces + {"crypto.Hash", "type Hash uint"}, + {"go/ast.ObjKind", "type ObjKind int"}, + {"go/types.Qualifier", "type Qualifier func(*Package) string"}, + {"go/types.Comparable", "func Comparable(T Type) bool"}, + {"math.Pi", "const Pi untyped float"}, + {"math.Sin", "func Sin(x float64) float64"}, + {"go/ast.NotNilFilter", "func NotNilFilter(_ string, v reflect.Value) bool"}, + {"go/internal/gcimporter.BImportData", "func BImportData(fset *go/token.FileSet, imports map[string]*go/types.Package, data []byte, path string) (_ int, pkg *go/types.Package, err error)"}, + + // interfaces + {"context.Context", "type Context interface{Deadline() (deadline time.Time, ok bool); Done() <-chan struct{}; Err() error; Value(key interface{}) interface{}}"}, + {"crypto.Decrypter", "type Decrypter interface{Decrypt(rand io.Reader, msg []byte, opts DecrypterOpts) (plaintext []byte, err error); Public() PublicKey}"}, + {"encoding.BinaryMarshaler", "type BinaryMarshaler interface{MarshalBinary() (data []byte, err error)}"}, + {"io.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"}, + {"io.ReadWriter", "type ReadWriter interface{Reader; Writer}"}, + {"go/ast.Node", "type Node interface{End() go/token.Pos; Pos() go/token.Pos}"}, + {"go/types.Type", "type Type interface{String() string; Underlying() Type}"}, +} + +func TestImportedTypes(t *testing.T) { + skipSpecialPlatforms(t) + + // This package only handles gc export data. + if runtime.Compiler != "gc" { + t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) + } + + for _, test := range importedObjectTests { + s := strings.Split(test.name, ".") + if len(s) != 2 { + t.Fatal("inconsistent test data") + } + importPath := s[0] + objName := s[1] + + pkg, err := Import(make(map[string]*types.Package), importPath, ".") + if err != nil { + t.Error(err) + continue + } + + obj := pkg.Scope().Lookup(objName) + if obj == nil { + t.Errorf("%s: object not found", test.name) + continue + } + + got := types.ObjectString(obj, types.RelativeTo(pkg)) + if got != test.want { + t.Errorf("%s: got %q; want %q", test.name, got, test.want) + } + + if named, _ := obj.Type().(*types.Named); named != nil { + verifyInterfaceMethodRecvs(t, named, 0) + } + } +} + +// verifyInterfaceMethodRecvs verifies that method receiver types +// are named if the methods belong to a named interface type. +func verifyInterfaceMethodRecvs(t *testing.T, named *types.Named, level int) { + // avoid endless recursion in case of an embedding bug that lead to a cycle + if level > 10 { + t.Errorf("%s: embeds itself", named) + return + } + + iface, _ := named.Underlying().(*types.Interface) + if iface == nil { + return // not an interface + } + + // check explicitly declared methods + for i := 0; i < iface.NumExplicitMethods(); i++ { + m := iface.ExplicitMethod(i) + recv := m.Type().(*types.Signature).Recv() + if recv == nil { + t.Errorf("%s: missing receiver type", m) + continue + } + if recv.Type() != named { + t.Errorf("%s: got recv type %s; want %s", m, recv.Type(), named) + } + } + + // check embedded interfaces (if they are named, too) + for i := 0; i < iface.NumEmbeddeds(); i++ { + // embedding of interfaces cannot have cycles; recursion will terminate + if etype, _ := iface.EmbeddedType(i).(*types.Named); etype != nil { + verifyInterfaceMethodRecvs(t, etype, level+1) + } + } +} +func TestIssue25301(t *testing.T) { + skipSpecialPlatforms(t) + + // This package only handles gc export data. + if runtime.Compiler != "gc" { + t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) + } + + // On windows, we have to set the -D option for the compiler to avoid having a drive + // letter and an illegal ':' in the import path - just skip it (see also issue #3483). + if runtime.GOOS == "windows" { + t.Skip("avoid dealing with relative paths/drive letters on windows") + } + + if f := compile(t, "testdata", "issue25301.go"); f != "" { + defer os.Remove(f) + } + + importPkg(t, "./testdata/issue25301") +} diff --git a/go/internal/gcimporter/gcimporter_test.go b/go/internal/gcimporter/gcimporter_test.go index dce607fd..bfcb7389 100644 --- a/go/internal/gcimporter/gcimporter_test.go +++ b/go/internal/gcimporter/gcimporter_test.go @@ -252,95 +252,6 @@ func TestImportStdLib(t *testing.T) { t.Logf("tested %d imports", nimports) } -var importedObjectTests = []struct { - name string - want string -}{ - {"math.Pi", "const Pi untyped float"}, - {"io.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"}, - // Go 1.7 and 1.8 don't know about embedded interfaces. Leave this - // test out for now - the code is tested in the std library anyway. - // TODO(gri) enable again once we're off 1.7 and 1.8. - // {"io.ReadWriter", "type ReadWriter interface{Reader; Writer}"}, - {"math.Sin", "func Sin(x float64) float64"}, - // TODO(gri) Add additional tests which are now present in the - // corresponding std library version of this file. -} - -func TestImportedTypes(t *testing.T) { - skipSpecialPlatforms(t) - - // This package only handles gc export data. - if runtime.Compiler != "gc" { - t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) - } - - for _, test := range importedObjectTests { - s := strings.Split(test.name, ".") - if len(s) != 2 { - t.Fatal("inconsistent test data") - } - importPath := s[0] - objName := s[1] - - pkg, err := Import(make(map[string]*types.Package), importPath, ".") - if err != nil { - t.Error(err) - continue - } - - obj := pkg.Scope().Lookup(objName) - if obj == nil { - t.Errorf("%s: object not found", test.name) - continue - } - - got := types.ObjectString(obj, types.RelativeTo(pkg)) - if got != test.want { - t.Errorf("%s: got %q; want %q", test.name, got, test.want) - } - - if named, _ := obj.Type().(*types.Named); named != nil { - verifyInterfaceMethodRecvs(t, named, 0) - } - } -} - -// verifyInterfaceMethodRecvs verifies that method receiver types -// are named if the methods belong to a named interface type. -func verifyInterfaceMethodRecvs(t *testing.T, named *types.Named, level int) { - // avoid endless recursion in case of an embedding bug that lead to a cycle - if level > 10 { - t.Errorf("%s: embeds itself", named) - return - } - - iface, _ := named.Underlying().(*types.Interface) - if iface == nil { - return // not an interface - } - - // check explicitly declared methods - for i := 0; i < iface.NumExplicitMethods(); i++ { - m := iface.ExplicitMethod(i) - recv := m.Type().(*types.Signature).Recv() - if recv == nil { - t.Errorf("%s: missing receiver type", m) - continue - } - if recv.Type() != named { - t.Errorf("%s: got recv type %s; want %s", m, recv.Type(), named) - } - } - - // check embedded interfaces (if they are named, too) - for i := 0; i < iface.NumEmbeddeds(); i++ { - // embedding of interfaces cannot have cycles; recursion will terminate - if etype, _ := embeddedType(iface, i).(*types.Named); etype != nil { - verifyInterfaceMethodRecvs(t, etype, level+1) - } - } -} func TestIssue5815(t *testing.T) { skipSpecialPlatforms(t) @@ -556,27 +467,6 @@ func TestIssue20046(t *testing.T) { } } -func TestIssue25301(t *testing.T) { - skipSpecialPlatforms(t) - - // This package only handles gc export data. - if runtime.Compiler != "gc" { - t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler) - } - - // On windows, we have to set the -D option for the compiler to avoid having a drive - // letter and an illegal ':' in the import path - just skip it (see also issue #3483). - if runtime.GOOS == "windows" { - t.Skip("avoid dealing with relative paths/drive letters on windows") - } - - if f := compile(t, "testdata", "issue25301.go"); f != "" { - defer os.Remove(f) - } - - importPkg(t, "./testdata/issue25301") -} - func importPkg(t *testing.T, path string) *types.Package { pkg, err := Import(make(map[string]*types.Package), path, ".") if err != nil { diff --git a/go/internal/gcimporter/newInterface10.go b/go/internal/gcimporter/newInterface10.go index 0aca5711..463f2522 100644 --- a/go/internal/gcimporter/newInterface10.go +++ b/go/internal/gcimporter/newInterface10.go @@ -19,7 +19,3 @@ func newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interfac } return types.NewInterface(methods, named) } - -func embeddedType(iface *types.Interface, i int) types.Type { - return iface.Embedded(i) -} diff --git a/go/internal/gcimporter/newInterface11.go b/go/internal/gcimporter/newInterface11.go index e802f8a3..58d1735e 100644 --- a/go/internal/gcimporter/newInterface11.go +++ b/go/internal/gcimporter/newInterface11.go @@ -11,7 +11,3 @@ import "go/types" func newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface { return types.NewInterface2(methods, embeddeds) } - -func embeddedType(iface *types.Interface, i int) types.Type { - return iface.EmbeddedType(i) -}