1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
23 // skipSpecialPlatforms causes the test to be skipped for platforms where
24 // builders (build.golang.org) don't have access to compiled packages for
26 func skipSpecialPlatforms(t
*testing
.T
) {
27 switch platform
:= runtime
.GOOS
+ "-" + runtime
.GOARCH
; platform
{
33 t
.Skipf("no compiled packages available for import on %s", platform
)
37 func compile(t
*testing
.T
, dirname
, filename
string) string {
38 cmd
:= exec
.Command(testenv
.GoToolPath(t
), "tool", "compile", filename
)
40 out
, err
:= cmd
.CombinedOutput()
43 t
.Fatalf("go tool compile %s failed: %s", filename
, err
)
45 // filename should end with ".go"
46 return filepath
.Join(dirname
, filename
[:len(filename
)-2]+"o")
49 func testPath(t
*testing
.T
, path
, srcDir
string) *types
.Package
{
51 pkg
, err
:= Import(make(map[string]*types
.Package
), path
, srcDir
)
53 t
.Errorf("testPath(%s): %s", path
, err
)
56 t
.Logf("testPath(%s): %v", path
, time
.Since(t0
))
60 const maxTime
= 30 * time
.Second
62 func testDir(t
*testing
.T
, dir
string, endTime time
.Time
) (nimports
int) {
63 dirname
:= filepath
.Join(runtime
.GOROOT(), "pkg", runtime
.GOOS
+"_"+runtime
.GOARCH
, dir
)
64 list
, err
:= ioutil
.ReadDir(dirname
)
66 t
.Fatalf("testDir(%s): %s", dirname
, err
)
68 for _
, f
:= range list
{
69 if time
.Now().After(endTime
) {
70 t
.Log("testing time used up")
76 for _
, ext
:= range pkgExts
{
77 if strings
.HasSuffix(f
.Name(), ext
) {
78 name
:= f
.Name()[0 : len(f
.Name())-len(ext
)] // remove extension
79 if testPath(t
, filepath
.Join(dir
, name
), dir
) != nil {
85 nimports
+= testDir(t
, filepath
.Join(dir
, f
.Name()), endTime
)
91 func TestImportTestdata(t
*testing
.T
) {
92 // This package only handles gc export data.
93 if runtime
.Compiler
!= "gc" {
94 t
.Skipf("gc-built packages not available (compiler = %s)", runtime
.Compiler
)
97 if outFn
:= compile(t
, "testdata", "exports.go"); outFn
!= "" {
98 defer os
.Remove(outFn
)
101 if pkg
:= testPath(t
, "./testdata/exports", "."); pkg
!= nil {
102 // The package's Imports list must include all packages
103 // explicitly imported by exports.go, plus all packages
104 // referenced indirectly via exported objects in exports.go.
105 // With the textual export format, the list may also include
106 // additional packages that are not strictly required for
107 // import processing alone (they are exported to err "on
109 // TODO(gri) update the want list to be precise, now that
110 // the textual export data is gone.
111 got
:= fmt
.Sprint(pkg
.Imports())
112 for _
, want
:= range []string{"go/ast", "go/token"} {
113 if !strings
.Contains(got
, want
) {
114 t
.Errorf(`Package("exports").Imports() = %s, does not contain %s`, got
, want
)
120 func TestVersionHandling(t
*testing
.T
) {
121 skipSpecialPlatforms(t
) // we really only need to exclude nacl platforms, but this is fine
123 // This package only handles gc export data.
124 if runtime
.Compiler
!= "gc" {
125 t
.Skipf("gc-built packages not available (compiler = %s)", runtime
.Compiler
)
128 const dir
= "./testdata/versions"
129 list
, err
:= ioutil
.ReadDir(dir
)
134 for _
, f
:= range list
{
136 if !strings
.HasSuffix(name
, ".a") {
137 continue // not a package file
139 if strings
.Contains(name
, "corrupted") {
140 continue // don't process a leftover corrupted file
142 pkgpath
:= "./" + name
[:len(name
)-2]
144 // test that export data can be imported
145 _
, err
:= Import(make(map[string]*types
.Package
), pkgpath
, dir
)
147 t
.Errorf("import %q failed: %v", pkgpath
, err
)
151 // create file with corrupted export data
153 data
, err
:= ioutil
.ReadFile(filepath
.Join(dir
, name
))
157 // 2) find export data
158 i
:= bytes
.Index(data
, []byte("\n$$B\n")) + 5
159 j
:= bytes
.Index(data
[i
:], []byte("\n$$\n")) + i
160 if i
< 0 || j
< 0 || i
> j
{
161 t
.Fatalf("export data section not found (i = %d, j = %d)", i
, j
)
163 // 3) corrupt the data (increment every 7th byte)
164 for k
:= j
- 13; k
>= i
; k
-= 7 {
168 pkgpath
+= "_corrupted"
169 filename
:= filepath
.Join(dir
, pkgpath
) + ".a"
170 ioutil
.WriteFile(filename
, data
, 0666)
171 defer os
.Remove(filename
)
173 // test that importing the corrupted file results in an error
174 _
, err
= Import(make(map[string]*types
.Package
), pkgpath
, dir
)
176 t
.Errorf("import corrupted %q succeeded", pkgpath
)
177 } else if msg
:= err
.Error(); !strings
.Contains(msg
, "version skew") {
178 t
.Errorf("import %q error incorrect (%s)", pkgpath
, msg
)
183 func TestImportStdLib(t
*testing
.T
) {
184 skipSpecialPlatforms(t
)
186 // This package only handles gc export data.
187 if runtime
.Compiler
!= "gc" {
188 t
.Skipf("gc-built packages not available (compiler = %s)", runtime
.Compiler
)
192 if testing
.Short() && testenv
.Builder() == "" {
193 dt
= 10 * time
.Millisecond
195 nimports
:= testDir(t
, "", time
.Now().Add(dt
)) // installed packages
196 t
.Logf("tested %d imports", nimports
)
199 var importedObjectTests
= []struct {
203 {"math.Pi", "const Pi untyped float"},
204 {"io.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"},
205 {"io.ReadWriter", "type ReadWriter interface{Reader; Writer}"},
206 {"math.Sin", "func Sin(x float64) float64"},
207 // TODO(gri) add more tests
210 func TestImportedTypes(t
*testing
.T
) {
211 skipSpecialPlatforms(t
)
213 // This package only handles gc export data.
214 if runtime
.Compiler
!= "gc" {
215 t
.Skipf("gc-built packages not available (compiler = %s)", runtime
.Compiler
)
218 for _
, test
:= range importedObjectTests
{
219 s
:= strings
.Split(test
.name
, ".")
221 t
.Fatal("inconsistent test data")
226 pkg
, err
:= Import(make(map[string]*types
.Package
), importPath
, ".")
232 obj
:= pkg
.Scope().Lookup(objName
)
234 t
.Errorf("%s: object not found", test
.name
)
238 got
:= types
.ObjectString(obj
, types
.RelativeTo(pkg
))
239 if got
!= test
.want
{
240 t
.Errorf("%s: got %q; want %q", test
.name
, got
, test
.want
)
245 func TestIssue5815(t
*testing
.T
) {
246 skipSpecialPlatforms(t
)
248 // This package only handles gc export data.
249 if runtime
.Compiler
!= "gc" {
250 t
.Skipf("gc-built packages not available (compiler = %s)", runtime
.Compiler
)
253 pkg
:= importPkg(t
, "strings")
256 for _
, name
:= range scope
.Names() {
257 obj
:= scope
.Lookup(name
)
258 if obj
.Pkg() == nil {
259 t
.Errorf("no pkg for %s", obj
)
261 if tname
, _
:= obj
.(*types
.TypeName
); tname
!= nil {
262 named
:= tname
.Type().(*types
.Named
)
263 for i
:= 0; i
< named
.NumMethods(); i
++ {
266 t
.Errorf("no pkg for %s", m
)
273 // Smoke test to ensure that imported methods get the correct package.
274 func TestCorrectMethodPackage(t
*testing
.T
) {
275 skipSpecialPlatforms(t
)
277 // This package only handles gc export data.
278 if runtime
.Compiler
!= "gc" {
279 t
.Skipf("gc-built packages not available (compiler = %s)", runtime
.Compiler
)
282 imports
:= make(map[string]*types
.Package
)
283 _
, err
:= Import(imports
, "net/http", ".")
288 mutex
:= imports
["sync"].Scope().Lookup("Mutex").(*types
.TypeName
).Type()
289 mset
:= types
.NewMethodSet(types
.NewPointer(mutex
)) // methods of *sync.Mutex
290 sel
:= mset
.Lookup(nil, "Lock")
291 lock
:= sel
.Obj().(*types
.Func
)
292 if got
, want
:= lock
.Pkg().Path(), "sync"; got
!= want
{
293 t
.Errorf("got package path %q; want %q", got
, want
)
297 func TestIssue13566(t
*testing
.T
) {
298 skipSpecialPlatforms(t
)
300 // This package only handles gc export data.
301 if runtime
.Compiler
!= "gc" {
302 t
.Skipf("gc-built packages not available (compiler = %s)", runtime
.Compiler
)
305 // On windows, we have to set the -D option for the compiler to avoid having a drive
306 // letter and an illegal ':' in the import path - just skip it (see also issue #3483).
307 if runtime
.GOOS
== "windows" {
308 t
.Skip("avoid dealing with relative paths/drive letters on windows")
311 if f
:= compile(t
, "testdata", "a.go"); f
!= "" {
314 if f
:= compile(t
, "testdata", "b.go"); f
!= "" {
318 // import must succeed (test for issue at hand)
319 pkg
:= importPkg(t
, "./testdata/b")
321 // make sure all indirectly imported packages have names
322 for _
, imp
:= range pkg
.Imports() {
323 if imp
.Name() == "" {
324 t
.Errorf("no name for %s package", imp
.Path())
329 func TestIssue13898(t
*testing
.T
) {
330 skipSpecialPlatforms(t
)
332 // This package only handles gc export data.
333 if runtime
.Compiler
!= "gc" {
334 t
.Skipf("gc-built packages not available (compiler = %s)", runtime
.Compiler
)
337 // import go/internal/gcimporter which imports go/types partially
338 imports
:= make(map[string]*types
.Package
)
339 _
, err
:= Import(imports
, "go/internal/gcimporter", ".")
344 // look for go/types package
345 var goTypesPkg
*types
.Package
346 for path
, pkg
:= range imports
{
347 if path
== "go/types" {
352 if goTypesPkg
== nil {
353 t
.Fatal("go/types not found")
356 // look for go/types.Object type
357 obj
:= lookupObj(t
, goTypesPkg
.Scope(), "Object")
358 typ
, ok
:= obj
.Type().(*types
.Named
)
360 t
.Fatalf("go/types.Object type is %v; wanted named type", typ
)
363 // lookup go/types.Object.Pkg method
364 m
, index
, indirect
:= types
.LookupFieldOrMethod(typ
, false, nil, "Pkg")
366 t
.Fatalf("go/types.Object.Pkg not found (index = %v, indirect = %v)", index
, indirect
)
369 // the method must belong to go/types
370 if m
.Pkg().Path() != "go/types" {
371 t
.Fatalf("found %v; want go/types", m
.Pkg())
375 func TestIssue15517(t
*testing
.T
) {
376 skipSpecialPlatforms(t
)
378 // This package only handles gc export data.
379 if runtime
.Compiler
!= "gc" {
380 t
.Skipf("gc-built packages not available (compiler = %s)", runtime
.Compiler
)
383 // On windows, we have to set the -D option for the compiler to avoid having a drive
384 // letter and an illegal ':' in the import path - just skip it (see also issue #3483).
385 if runtime
.GOOS
== "windows" {
386 t
.Skip("avoid dealing with relative paths/drive letters on windows")
389 if f
:= compile(t
, "testdata", "p.go"); f
!= "" {
393 // Multiple imports of p must succeed without redeclaration errors.
394 // We use an import path that's not cleaned up so that the eventual
395 // file path for the package is different from the package path; this
396 // will expose the error if it is present.
398 // (Issue: Both the textual and the binary importer used the file path
399 // of the package to be imported as key into the shared packages map.
400 // However, the binary importer then used the package path to identify
401 // the imported package to mark it as complete; effectively marking the
402 // wrong package as complete. By using an "unclean" package path, the
403 // file and package path are different, exposing the problem if present.
404 // The same issue occurs with vendoring.)
405 imports
:= make(map[string]*types
.Package
)
406 for i
:= 0; i
< 3; i
++ {
407 if _
, err
:= Import(imports
, "./././testdata/p", "."); err
!= nil {
413 func TestIssue15920(t
*testing
.T
) {
414 skipSpecialPlatforms(t
)
416 // This package only handles gc export data.
417 if runtime
.Compiler
!= "gc" {
418 t
.Skipf("gc-built packages not available (compiler = %s)", runtime
.Compiler
)
421 // On windows, we have to set the -D option for the compiler to avoid having a drive
422 // letter and an illegal ':' in the import path - just skip it (see also issue #3483).
423 if runtime
.GOOS
== "windows" {
424 t
.Skip("avoid dealing with relative paths/drive letters on windows")
427 if f
:= compile(t
, "testdata", "issue15920.go"); f
!= "" {
431 importPkg(t
, "./testdata/issue15920")
434 func TestIssue20046(t
*testing
.T
) {
435 skipSpecialPlatforms(t
)
437 // This package only handles gc export data.
438 if runtime
.Compiler
!= "gc" {
439 t
.Skipf("gc-built packages not available (compiler = %s)", runtime
.Compiler
)
442 // On windows, we have to set the -D option for the compiler to avoid having a drive
443 // letter and an illegal ':' in the import path - just skip it (see also issue #3483).
444 if runtime
.GOOS
== "windows" {
445 t
.Skip("avoid dealing with relative paths/drive letters on windows")
448 if f
:= compile(t
, "testdata", "issue20046.go"); f
!= "" {
452 // "./issue20046".V.M must exist
453 pkg
:= importPkg(t
, "./testdata/issue20046")
454 obj
:= lookupObj(t
, pkg
.Scope(), "V")
455 if m
, index
, indirect
:= types
.LookupFieldOrMethod(obj
.Type(), false, nil, "M"); m
== nil {
456 t
.Fatalf("V.M not found (index = %v, indirect = %v)", index
, indirect
)
460 func importPkg(t
*testing
.T
, path
string) *types
.Package
{
461 pkg
, err
:= Import(make(map[string]*types
.Package
), path
, ".")
468 func lookupObj(t
*testing
.T
, scope
*types
.Scope
, name
string) types
.Object
{
469 if obj
:= scope
.Lookup(name
); obj
!= nil {
472 t
.Fatalf("%s not found", name
)