GoPLS Viewer

Home|gopls/internal/gcimporter/gcimporter_test.go
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.
4
5// This file is a copy of $GOROOT/src/go/internal/gcimporter/gcimporter_test.go,
6// adjusted to make it build with code from (std lib) internal/testenv copied.
7
8package gcimporter
9
10import (
11    "bytes"
12    "fmt"
13    "go/ast"
14    "go/build"
15    "go/constant"
16    goimporter "go/importer"
17    goparser "go/parser"
18    "go/token"
19    "go/types"
20    "io/ioutil"
21    "os"
22    "os/exec"
23    "path"
24    "path/filepath"
25    "runtime"
26    "strings"
27    "testing"
28    "time"
29
30    "golang.org/x/tools/internal/goroot"
31    "golang.org/x/tools/internal/testenv"
32)
33
34func TestMain(m *testing.M) {
35    testenv.ExitIfSmallMachine()
36    os.Exit(m.Run())
37}
38
39// ----------------------------------------------------------------------------
40
41func needsCompiler(t *testing.Tcompiler string) {
42    if runtime.Compiler == compiler {
43        return
44    }
45    switch compiler {
46    case "gc":
47        t.Skipf("gc-built packages not available (compiler = %s)"runtime.Compiler)
48    }
49}
50
51// compile runs the compiler on filename, with dirname as the working directory,
52// and writes the output file to outdirname.
53// compile gives the resulting package a packagepath of p.
54func compile(t *testing.Tdirnamefilenameoutdirname stringpackagefiles map[string]stringstring {
55    return compilePkg(tdirnamefilenameoutdirnamepackagefiles"p")
56}
57
58func compilePkg(t *testing.Tdirnamefilenameoutdirname stringpackagefiles map[string]stringpkg stringstring {
59    testenv.NeedsGoBuild(t)
60
61    // filename must end with ".go"
62    basename := strings.TrimSuffix(filepath.Base(filename), ".go")
63    ok := filename != basename
64    if !ok {
65        t.Fatalf("filename doesn't end in .go: %s"filename)
66    }
67    objname := basename + ".o"
68    outname := filepath.Join(outdirnameobjname)
69
70    importcfgfile := os.DevNull
71    if len(packagefiles) > 0 {
72        importcfgfile = filepath.Join(outdirnamebasename) + ".importcfg"
73        importcfg := new(bytes.Buffer)
74        fmt.Fprintf(importcfg"# import config")
75        for kv := range packagefiles {
76            fmt.Fprintf(importcfg"\npackagefile %s=%s\n"kv)
77        }
78        if err := os.WriteFile(importcfgfileimportcfg.Bytes(), 0655); err != nil {
79            t.Fatal(err)
80        }
81    }
82
83    importreldir := strings.ReplaceAll(outdirnamestring(os.PathSeparator), "/")
84    cmd := exec.Command("go""tool""compile""-p"pkg"-D"importreldir"-importcfg"importcfgfile"-o"outnamefilename)
85    cmd.Dir = dirname
86    outerr := cmd.CombinedOutput()
87    if err != nil {
88        t.Logf("%s"out)
89        t.Fatalf("go tool compile %s failed: %s"filenameerr)
90    }
91    return outname
92}
93
94func testPath(t *testing.TpathsrcDir string) *types.Package {
95    t0 := time.Now()
96    pkgerr := Import(make(map[string]*types.Package), pathsrcDirnil)
97    if err != nil {
98        t.Errorf("testPath(%s): %s"patherr)
99        return nil
100    }
101    t.Logf("testPath(%s): %v"pathtime.Since(t0))
102    return pkg
103}
104
105func mktmpdir(t *testing.Tstring {
106    tmpdirerr := ioutil.TempDir("""gcimporter_test")
107    if err != nil {
108        t.Fatal("mktmpdir:"err)
109    }
110    if err := os.Mkdir(filepath.Join(tmpdir"testdata"), 0700); err != nil {
111        os.RemoveAll(tmpdir)
112        t.Fatal("mktmpdir:"err)
113    }
114    return tmpdir
115}
116
117const testfile = "exports.go"
118
119func TestImportTestdata(t *testing.T) {
120    needsCompiler(t"gc")
121    testenv.NeedsGoBuild(t// to find stdlib export data in the build cache
122
123    tmpdir := mktmpdir(t)
124    defer os.RemoveAll(tmpdir)
125
126    packageFiles := map[string]string{}
127    for _pkg := range []string{"go/ast""go/token"} {
128        export_ := FindPkg(pkg"testdata")
129        if export == "" {
130            t.Fatalf("no export data found for %s"pkg)
131        }
132        packageFiles[pkg] = export
133    }
134
135    compile(t"testdata"testfilefilepath.Join(tmpdir"testdata"), packageFiles)
136
137    // filename should end with ".go"
138    filename := testfile[:len(testfile)-3]
139    if pkg := testPath(t"./testdata/"+filenametmpdir); pkg != nil {
140        // The package's Imports list must include all packages
141        // explicitly imported by testfile, plus all packages
142        // referenced indirectly via exported objects in testfile.
143        // With the textual export format (when run against Go1.6),
144        // the list may also include additional packages that are
145        // not strictly required for import processing alone (they
146        // are exported to err "on the safe side").
147        // For now, we just test the presence of a few packages
148        // that we know are there for sure.
149        got := fmt.Sprint(pkg.Imports())
150        wants := []string{"go/ast""go/token"}
151        if unifiedIR {
152            wants = []string{"go/ast"}
153        }
154        for _want := range wants {
155            if !strings.Contains(gotwant) {
156                t.Errorf(`Package("exports").Imports() = %s, does not contain %s`gotwant)
157            }
158        }
159    }
160}
161
162func TestImportTypeparamTests(t *testing.T) {
163    if testing.Short() {
164        t.Skipf("in short mode, skipping test that requires export data for all of std")
165    }
166
167    testenv.NeedsGo1Point(t18// requires generics
168    testenv.NeedsGoBuild(t)      // to find stdlib export data in the build cache
169
170    // This package only handles gc export data.
171    if runtime.Compiler != "gc" {
172        t.Skipf("gc-built packages not available (compiler = %s)"runtime.Compiler)
173    }
174
175    tmpdir := mktmpdir(t)
176    defer os.RemoveAll(tmpdir)
177
178    // Check go files in test/typeparam, except those that fail for a known
179    // reason.
180    rootDir := filepath.Join(runtime.GOROOT(), "test""typeparam")
181    listerr := os.ReadDir(rootDir)
182    if err != nil {
183        t.Fatal(err)
184    }
185
186    var skip map[string]string
187    if !unifiedIR {
188        // The Go 1.18 frontend still fails several cases.
189        skip = map[string]string{
190            "equal.go":      "inconsistent embedded sorting"// TODO(rfindley): investigate this.
191            "nested.go":     "fails to compile",              // TODO(rfindley): investigate this.
192            "issue47631.go""can not handle local type declarations",
193            "issue55101.go""fails to compile",
194        }
195    }
196
197    for _entry := range list {
198        if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".go") {
199            // For now, only consider standalone go files.
200            continue
201        }
202
203        t.Run(entry.Name(), func(t *testing.T) {
204            if reasonok := skip[entry.Name()]; ok {
205                t.Skip(reason)
206            }
207
208            filename := filepath.Join(rootDirentry.Name())
209            srcerr := os.ReadFile(filename)
210            if err != nil {
211                t.Fatal(err)
212            }
213            if !bytes.HasPrefix(src, []byte("// run")) && !bytes.HasPrefix(src, []byte("// compile")) {
214                // We're bypassing the logic of run.go here, so be conservative about
215                // the files we consider in an attempt to make this test more robust to
216                // changes in test/typeparams.
217                t.Skipf("not detected as a run test")
218            }
219
220            // Compile and import, and compare the resulting package with the package
221            // that was type-checked directly.
222            pkgFileserr := goroot.PkgfileMap()
223            if err != nil {
224                t.Fatal(err)
225            }
226            compile(trootDirentry.Name(), filepath.Join(tmpdir"testdata"), pkgFiles)
227            pkgName := strings.TrimSuffix(entry.Name(), ".go")
228            imported := importPkg(t"./testdata/"+pkgNametmpdir)
229            checked := checkFile(tfilenamesrc)
230
231            seen := make(map[string]bool)
232            for _name := range imported.Scope().Names() {
233                if !token.IsExported(name) {
234                    continue // ignore synthetic names like .inittask and .dict.*
235                }
236                seen[name] = true
237
238                importedObj := imported.Scope().Lookup(name)
239                got := types.ObjectString(importedObjtypes.RelativeTo(imported))
240                got = sanitizeObjectString(got)
241
242                checkedObj := checked.Scope().Lookup(name)
243                if checkedObj == nil {
244                    t.Fatalf("imported object %q was not type-checked"name)
245                }
246                want := types.ObjectString(checkedObjtypes.RelativeTo(checked))
247                want = sanitizeObjectString(want)
248
249                if got != want {
250                    t.Errorf("imported %q as %q, want %q"namegotwant)
251                }
252            }
253
254            for _name := range checked.Scope().Names() {
255                if !token.IsExported(name) || seen[name] {
256                    continue
257                }
258                t.Errorf("did not import object %q"name)
259            }
260        })
261    }
262}
263
264// sanitizeObjectString removes type parameter debugging markers from an object
265// string, to normalize it for comparison.
266// TODO(rfindley): this should not be necessary.
267func sanitizeObjectString(s stringstring {
268    var runes []rune
269    for _r := range s {
270        if '₀' <= r && r < '₀'+10 {
271            continue // trim type parameter subscripts
272        }
273        runes = append(runesr)
274    }
275    return string(runes)
276}
277
278func checkFile(t *testing.Tfilename stringsrc []byte) *types.Package {
279    fset := token.NewFileSet()
280    ferr := goparser.ParseFile(fsetfilenamesrc0)
281    if err != nil {
282        t.Fatal(err)
283    }
284    config := types.Config{
285        Importergoimporter.Default(),
286    }
287    pkgerr := config.Check(""fset, []*ast.File{f}, nil)
288    if err != nil {
289        t.Fatal(err)
290    }
291    return pkg
292}
293
294func TestVersionHandling(t *testing.T) {
295    if debug {
296        t.Skip("TestVersionHandling panics in debug mode")
297    }
298
299    // This package only handles gc export data.
300    needsCompiler(t"gc")
301
302    const dir = "./testdata/versions"
303    listerr := ioutil.ReadDir(dir)
304    if err != nil {
305        t.Fatal(err)
306    }
307
308    tmpdir := mktmpdir(t)
309    defer os.RemoveAll(tmpdir)
310    corruptdir := filepath.Join(tmpdir"testdata""versions")
311    if err := os.Mkdir(corruptdir0700); err != nil {
312        t.Fatal(err)
313    }
314
315    for _f := range list {
316        name := f.Name()
317        if !strings.HasSuffix(name".a") {
318            continue // not a package file
319        }
320        if strings.Contains(name"corrupted") {
321            continue // don't process a leftover corrupted file
322        }
323        pkgpath := "./" + name[:len(name)-2]
324
325        if testing.Verbose() {
326            t.Logf("importing %s"name)
327        }
328
329        // test that export data can be imported
330        _err := Import(make(map[string]*types.Package), pkgpathdirnil)
331        if err != nil {
332            // ok to fail if it fails with a newer version error for select files
333            if strings.Contains(err.Error(), "newer version") {
334                switch name {
335                case "test_go1.11_999b.a""test_go1.11_999i.a":
336                    continue
337                }
338                // fall through
339            }
340            t.Errorf("import %q failed: %v"pkgpatherr)
341            continue
342        }
343
344        // create file with corrupted export data
345        // 1) read file
346        dataerr := ioutil.ReadFile(filepath.Join(dirname))
347        if err != nil {
348            t.Fatal(err)
349        }
350        // 2) find export data
351        i := bytes.Index(data, []byte("\n$$B\n")) + 5
352        j := bytes.Index(data[i:], []byte("\n$$\n")) + i
353        if i < 0 || j < 0 || i > j {
354            t.Fatalf("export data section not found (i = %d, j = %d)"ij)
355        }
356        // 3) corrupt the data (increment every 7th byte)
357        for k := j - 13k >= ik -= 7 {
358            data[k]++
359        }
360        // 4) write the file
361        pkgpath += "_corrupted"
362        filename := filepath.Join(corruptdirpkgpath) + ".a"
363        ioutil.WriteFile(filenamedata0666)
364
365        // test that importing the corrupted file results in an error
366        _err = Import(make(map[string]*types.Package), pkgpathcorruptdirnil)
367        if err == nil {
368            t.Errorf("import corrupted %q succeeded"pkgpath)
369        } else if msg := err.Error(); !strings.Contains(msg"version skew") {
370            t.Errorf("import %q error incorrect (%s)"pkgpathmsg)
371        }
372    }
373}
374
375func TestImportStdLib(t *testing.T) {
376    if testing.Short() {
377        t.Skip("the imports can be expensive, and this test is especially slow when the build cache is empty")
378    }
379    // This package only handles gc export data.
380    needsCompiler(t"gc")
381    testenv.NeedsGoBuild(t// to find stdlib export data in the build cache
382
383    // Get list of packages in stdlib. Filter out test-only packages with {{if .GoFiles}} check.
384    var stderr bytes.Buffer
385    cmd := exec.Command("go""list""-f""{{if .GoFiles}}{{.ImportPath}}{{end}}""std")
386    cmd.Stderr = &stderr
387    outerr := cmd.Output()
388    if err != nil {
389        t.Fatalf("failed to run go list to determine stdlib packages: %v\nstderr:\n%v"errstderr.String())
390    }
391    pkgs := strings.Fields(string(out))
392
393    var nimports int
394    for _pkg := range pkgs {
395        t.Run(pkg, func(t *testing.T) {
396            if testPath(tpkgfilepath.Join(testenv.GOROOT(t), "src"path.Dir(pkg))) != nil {
397                nimports++
398            }
399        })
400    }
401    const minPkgs = 225 // 'GOOS=plan9 go1.18 list std | wc -l' reports 228; most other platforms have more.
402    if len(pkgs) < minPkgs {
403        t.Fatalf("too few packages (%d) were imported"nimports)
404    }
405
406    t.Logf("tested %d imports"nimports)
407}
408
409var importedObjectTests = []struct {
410    name string
411    want string
412}{
413    // non-interfaces
414    {"crypto.Hash""type Hash uint"},
415    {"go/ast.ObjKind""type ObjKind int"},
416    {"go/types.Qualifier""type Qualifier func(*Package) string"},
417    {"go/types.Comparable""func Comparable(T Type) bool"},
418    {"math.Pi""const Pi untyped float"},
419    {"math.Sin""func Sin(x float64) float64"},
420    {"go/ast.NotNilFilter""func NotNilFilter(_ string, v reflect.Value) bool"},
421    {"go/internal/gcimporter.FindPkg""func FindPkg(path string, srcDir string) (filename string, id string)"},
422
423    // interfaces
424    {"context.Context""type Context interface{Deadline() (deadline time.Time, ok bool); Done() <-chan struct{}; Err() error; Value(key any) any}"},
425    {"crypto.Decrypter""type Decrypter interface{Decrypt(rand io.Reader, msg []byte, opts DecrypterOpts) (plaintext []byte, err error); Public() PublicKey}"},
426    {"encoding.BinaryMarshaler""type BinaryMarshaler interface{MarshalBinary() (data []byte, err error)}"},
427    {"io.Reader""type Reader interface{Read(p []byte) (n int, err error)}"},
428    {"io.ReadWriter""type ReadWriter interface{Reader; Writer}"},
429    {"go/ast.Node""type Node interface{End() go/token.Pos; Pos() go/token.Pos}"},
430    {"go/types.Type""type Type interface{String() string; Underlying() Type}"},
431}
432
433// TODO(rsc): Delete this init func after x/tools no longer needs to test successfully with Go 1.17.
434func init() {
435    if build.Default.ReleaseTags[len(build.Default.ReleaseTags)-1] <= "go1.17" {
436        for i := range importedObjectTests {
437            if importedObjectTests[i].name == "context.Context" {
438                // Expand any to interface{}.
439                importedObjectTests[i].want = "type Context interface{Deadline() (deadline time.Time, ok bool); Done() <-chan struct{}; Err() error; Value(key interface{}) interface{}}"
440            }
441        }
442    }
443}
444
445func TestImportedTypes(t *testing.T) {
446    // This package only handles gc export data.
447    needsCompiler(t"gc")
448    testenv.NeedsGoBuild(t// to find stdlib export data in the build cache
449
450    for _test := range importedObjectTests {
451        obj := importObject(ttest.name)
452        if obj == nil {
453            continue // error reported elsewhere
454        }
455        got := types.ObjectString(objtypes.RelativeTo(obj.Pkg()))
456
457        // TODO(rsc): Delete this block once go.dev/cl/368254 lands.
458        if got != test.want && test.want == strings.ReplaceAll(got"interface{}""any") {
459            got = test.want
460        }
461
462        if got != test.want {
463            t.Errorf("%s: got %q; want %q"test.namegottest.want)
464        }
465
466        if named_ := obj.Type().(*types.Named); named != nil {
467            verifyInterfaceMethodRecvs(tnamed0)
468        }
469    }
470}
471
472func TestImportedConsts(t *testing.T) {
473    testenv.NeedsGoBuild(t// to find stdlib export data in the build cache
474
475    tests := []struct {
476        name string
477        want constant.Kind
478    }{
479        {"math.Pi"constant.Float},
480        {"math.MaxFloat64"constant.Float},
481        {"math.MaxInt64"constant.Int},
482    }
483
484    for _test := range tests {
485        obj := importObject(ttest.name)
486        if got := obj.(*types.Const).Val().Kind(); got != test.want {
487            t.Errorf("%s: imported as constant.Kind(%v), want constant.Kind(%v)"test.namegottest.want)
488        }
489    }
490}
491
492// importObject imports the object specified by a name of the form
493// <import path>.<object name>, e.g. go/types.Type.
494//
495// If any errors occur they are reported via t and the resulting object will
496// be nil.
497func importObject(t *testing.Tname stringtypes.Object {
498    s := strings.Split(name".")
499    if len(s) != 2 {
500        t.Fatal("inconsistent test data")
501    }
502    importPath := s[0]
503    objName := s[1]
504
505    pkgerr := Import(make(map[string]*types.Package), importPath"."nil)
506    if err != nil {
507        t.Error(err)
508        return nil
509    }
510
511    obj := pkg.Scope().Lookup(objName)
512    if obj == nil {
513        t.Errorf("%s: object not found"name)
514        return nil
515    }
516    return obj
517}
518
519// verifyInterfaceMethodRecvs verifies that method receiver types
520// are named if the methods belong to a named interface type.
521func verifyInterfaceMethodRecvs(t *testing.Tnamed *types.Namedlevel int) {
522    // avoid endless recursion in case of an embedding bug that lead to a cycle
523    if level > 10 {
524        t.Errorf("%s: embeds itself"named)
525        return
526    }
527
528    iface_ := named.Underlying().(*types.Interface)
529    if iface == nil {
530        return // not an interface
531    }
532
533    // check explicitly declared methods
534    for i := 0i < iface.NumExplicitMethods(); i++ {
535        m := iface.ExplicitMethod(i)
536        recv := m.Type().(*types.Signature).Recv()
537        if recv == nil {
538            t.Errorf("%s: missing receiver type"m)
539            continue
540        }
541        if recv.Type() != named {
542            t.Errorf("%s: got recv type %s; want %s"mrecv.Type(), named)
543        }
544    }
545
546    // check embedded interfaces (if they are named, too)
547    for i := 0i < iface.NumEmbeddeds(); i++ {
548        // embedding of interfaces cannot have cycles; recursion will terminate
549        if etype_ := iface.EmbeddedType(i).(*types.Named); etype != nil {
550            verifyInterfaceMethodRecvs(tetypelevel+1)
551        }
552    }
553}
554
555func TestIssue5815(t *testing.T) {
556    // This package only handles gc export data.
557    needsCompiler(t"gc")
558    testenv.NeedsGoBuild(t// to find stdlib export data in the build cache
559
560    pkg := importPkg(t"strings"".")
561
562    scope := pkg.Scope()
563    for _name := range scope.Names() {
564        obj := scope.Lookup(name)
565        if obj.Pkg() == nil {
566            t.Errorf("no pkg for %s"obj)
567        }
568        if tname_ := obj.(*types.TypeName); tname != nil {
569            named := tname.Type().(*types.Named)
570            for i := 0i < named.NumMethods(); i++ {
571                m := named.Method(i)
572                if m.Pkg() == nil {
573                    t.Errorf("no pkg for %s"m)
574                }
575            }
576        }
577    }
578}
579
580// Smoke test to ensure that imported methods get the correct package.
581func TestCorrectMethodPackage(t *testing.T) {
582    // This package only handles gc export data.
583    needsCompiler(t"gc")
584    testenv.NeedsGoBuild(t// to find stdlib export data in the build cache
585
586    imports := make(map[string]*types.Package)
587    _err := Import(imports"net/http""."nil)
588    if err != nil {
589        t.Fatal(err)
590    }
591
592    mutex := imports["sync"].Scope().Lookup("Mutex").(*types.TypeName).Type()
593    mset := types.NewMethodSet(types.NewPointer(mutex)) // methods of *sync.Mutex
594    sel := mset.Lookup(nil"Lock")
595    lock := sel.Obj().(*types.Func)
596    if gotwant := lock.Pkg().Path(), "sync"got != want {
597        t.Errorf("got package path %q; want %q"gotwant)
598    }
599}
600
601func TestIssue13566(t *testing.T) {
602    // This package only handles gc export data.
603    needsCompiler(t"gc")
604    testenv.NeedsGoBuild(t// to find stdlib export data in the build cache
605
606    // On windows, we have to set the -D option for the compiler to avoid having a drive
607    // letter and an illegal ':' in the import path - just skip it (see also issue #3483).
608    if runtime.GOOS == "windows" {
609        t.Skip("avoid dealing with relative paths/drive letters on windows")
610    }
611
612    tmpdir := mktmpdir(t)
613    defer os.RemoveAll(tmpdir)
614    testoutdir := filepath.Join(tmpdir"testdata")
615
616    // b.go needs to be compiled from the output directory so that the compiler can
617    // find the compiled package a. We pass the full path to compile() so that we
618    // don't have to copy the file to that directory.
619    bpatherr := filepath.Abs(filepath.Join("testdata""b.go"))
620    if err != nil {
621        t.Fatal(err)
622    }
623
624    jsonExport_ := FindPkg("encoding/json""testdata")
625    if jsonExport == "" {
626        t.Fatalf("no export data found for encoding/json")
627    }
628
629    compilePkg(t"testdata""a.go"testoutdir, map[string]string{"encoding/json"jsonExport}, apkg(testoutdir))
630    compile(ttestoutdirbpathtestoutdir, map[string]string{apkg(testoutdir): filepath.Join(testoutdir"a.o")})
631
632    // import must succeed (test for issue at hand)
633    pkg := importPkg(t"./testdata/b"tmpdir)
634
635    // make sure all indirectly imported packages have names
636    for _imp := range pkg.Imports() {
637        if imp.Name() == "" {
638            t.Errorf("no name for %s package"imp.Path())
639        }
640    }
641}
642
643func TestIssue13898(t *testing.T) {
644    // This package only handles gc export data.
645    needsCompiler(t"gc")
646    testenv.NeedsGoBuild(t// to find stdlib export data in the build cache
647
648    // import go/internal/gcimporter which imports go/types partially
649    imports := make(map[string]*types.Package)
650    _err := Import(imports"go/internal/gcimporter""."nil)
651    if err != nil {
652        t.Fatal(err)
653    }
654
655    // look for go/types package
656    var goTypesPkg *types.Package
657    for pathpkg := range imports {
658        if path == "go/types" {
659            goTypesPkg = pkg
660            break
661        }
662    }
663    if goTypesPkg == nil {
664        t.Fatal("go/types not found")
665    }
666
667    // look for go/types.Object type
668    obj := lookupObj(tgoTypesPkg.Scope(), "Object")
669    typok := obj.Type().(*types.Named)
670    if !ok {
671        t.Fatalf("go/types.Object type is %v; wanted named type"typ)
672    }
673
674    // lookup go/types.Object.Pkg method
675    mindexindirect := types.LookupFieldOrMethod(typfalsenil"Pkg")
676    if m == nil {
677        t.Fatalf("go/types.Object.Pkg not found (index = %v, indirect = %v)"indexindirect)
678    }
679
680    // the method must belong to go/types
681    if m.Pkg().Path() != "go/types" {
682        t.Fatalf("found %v; want go/types"m.Pkg())
683    }
684}
685
686func TestIssue15517(t *testing.T) {
687    // This package only handles gc export data.
688    needsCompiler(t"gc")
689
690    // On windows, we have to set the -D option for the compiler to avoid having a drive
691    // letter and an illegal ':' in the import path - just skip it (see also issue #3483).
692    if runtime.GOOS == "windows" {
693        t.Skip("avoid dealing with relative paths/drive letters on windows")
694    }
695
696    tmpdir := mktmpdir(t)
697    defer os.RemoveAll(tmpdir)
698
699    compile(t"testdata""p.go"filepath.Join(tmpdir"testdata"), nil)
700
701    // Multiple imports of p must succeed without redeclaration errors.
702    // We use an import path that's not cleaned up so that the eventual
703    // file path for the package is different from the package path; this
704    // will expose the error if it is present.
705    //
706    // (Issue: Both the textual and the binary importer used the file path
707    // of the package to be imported as key into the shared packages map.
708    // However, the binary importer then used the package path to identify
709    // the imported package to mark it as complete; effectively marking the
710    // wrong package as complete. By using an "unclean" package path, the
711    // file and package path are different, exposing the problem if present.
712    // The same issue occurs with vendoring.)
713    imports := make(map[string]*types.Package)
714    for i := 0i < 3i++ {
715        if _err := Import(imports"./././testdata/p"tmpdirnil); err != nil {
716            t.Fatal(err)
717        }
718    }
719}
720
721func TestIssue15920(t *testing.T) {
722    // This package only handles gc export data.
723    needsCompiler(t"gc")
724
725    // On windows, we have to set the -D option for the compiler to avoid having a drive
726    // letter and an illegal ':' in the import path - just skip it (see also issue #3483).
727    if runtime.GOOS == "windows" {
728        t.Skip("avoid dealing with relative paths/drive letters on windows")
729    }
730
731    compileAndImportPkg(t"issue15920")
732}
733
734func TestIssue20046(t *testing.T) {
735    // This package only handles gc export data.
736    needsCompiler(t"gc")
737
738    // On windows, we have to set the -D option for the compiler to avoid having a drive
739    // letter and an illegal ':' in the import path - just skip it (see also issue #3483).
740    if runtime.GOOS == "windows" {
741        t.Skip("avoid dealing with relative paths/drive letters on windows")
742    }
743
744    // "./issue20046".V.M must exist
745    pkg := compileAndImportPkg(t"issue20046")
746    obj := lookupObj(tpkg.Scope(), "V")
747    if mindexindirect := types.LookupFieldOrMethod(obj.Type(), falsenil"M"); m == nil {
748        t.Fatalf("V.M not found (index = %v, indirect = %v)"indexindirect)
749    }
750}
751
752func TestIssue25301(t *testing.T) {
753    // This package only handles gc export data.
754    needsCompiler(t"gc")
755
756    // On windows, we have to set the -D option for the compiler to avoid having a drive
757    // letter and an illegal ':' in the import path - just skip it (see also issue #3483).
758    if runtime.GOOS == "windows" {
759        t.Skip("avoid dealing with relative paths/drive letters on windows")
760    }
761
762    compileAndImportPkg(t"issue25301")
763}
764
765func TestIssue51836(t *testing.T) {
766    testenv.NeedsGo1Point(t18// requires generics
767
768    // This package only handles gc export data.
769    needsCompiler(t"gc")
770
771    // On windows, we have to set the -D option for the compiler to avoid having a drive
772    // letter and an illegal ':' in the import path - just skip it (see also issue #3483).
773    if runtime.GOOS == "windows" {
774        t.Skip("avoid dealing with relative paths/drive letters on windows")
775    }
776
777    tmpdir := mktmpdir(t)
778    defer os.RemoveAll(tmpdir)
779    testoutdir := filepath.Join(tmpdir"testdata")
780
781    dir := filepath.Join("testdata""issue51836")
782    // Following the pattern of TestIssue13898, aa.go needs to be compiled from
783    // the output directory. We pass the full path to compile() so that we don't
784    // have to copy the file to that directory.
785    bpatherr := filepath.Abs(filepath.Join(dir"aa.go"))
786    if err != nil {
787        t.Fatal(err)
788    }
789    compilePkg(tdir"a.go"testoutdirnilapkg(testoutdir))
790    compile(ttestoutdirbpathtestoutdir, map[string]string{apkg(testoutdir): filepath.Join(testoutdir"a.o")})
791
792    // import must succeed (test for issue at hand)
793    _ = importPkg(t"./testdata/aa"tmpdir)
794}
795
796func TestIssue57015(t *testing.T) {
797    testenv.NeedsGo1Point(t18// requires generics
798
799    // This package only handles gc export data.
800    needsCompiler(t"gc")
801
802    // On windows, we have to set the -D option for the compiler to avoid having a drive
803    // letter and an illegal ':' in the import path - just skip it (see also issue #3483).
804    if runtime.GOOS == "windows" {
805        t.Skip("avoid dealing with relative paths/drive letters on windows")
806    }
807
808    compileAndImportPkg(t"issue57015")
809}
810
811// apkg returns the package "a" prefixed by (as a package) testoutdir
812func apkg(testoutdir stringstring {
813    apkg := testoutdir + "/a"
814    if os.PathSeparator != '/' {
815        apkg = strings.ReplaceAll(apkgstring(os.PathSeparator), "/")
816    }
817    return apkg
818}
819
820func importPkg(t *testing.TpathsrcDir string) *types.Package {
821    pkgerr := Import(make(map[string]*types.Package), pathsrcDirnil)
822    if err != nil {
823        t.Fatal(err)
824    }
825    return pkg
826}
827
828func compileAndImportPkg(t *testing.Tname string) *types.Package {
829    tmpdir := mktmpdir(t)
830    defer os.RemoveAll(tmpdir)
831    compile(t"testdata"name+".go"filepath.Join(tmpdir"testdata"), nil)
832    return importPkg(t"./testdata/"+nametmpdir)
833}
834
835func lookupObj(t *testing.Tscope *types.Scopename stringtypes.Object {
836    if obj := scope.Lookup(name); obj != nil {
837        return obj
838    }
839    t.Fatalf("%s not found"name)
840    return nil
841}
842
MembersX
testPath.path
TestIssue5815.RangeStmt_17091.BlockStmt.obj
needsCompiler.t
TestImportTypeparamTests.skip
compilePkg.pkg
TestImportStdLib.cmd
lookupObj.t
compilePkg.outdirname
TestImportStdLib.nimports
verifyInterfaceMethodRecvs.BlockStmt.recv
TestIssue20046.t
importPkg.t
testenv
TestMain
needsCompiler
compilePkg.filename
TestImportTestdata.RangeStmt_3438.pkg
testPath.pkg
TestVersionHandling
TestIssue15517
TestImportTestdata.packageFiles
TestImportedTypes.RangeStmt_13994.BlockStmt.obj
TestImportedConsts.RangeStmt_14859.BlockStmt.obj
importObject.s
TestIssue5815.RangeStmt_17091.name
TestIssue13566.err
importPkg.srcDir
mktmpdir.tmpdir
importObject.obj
compilePkg.cmd
TestIssue5815.pkg
compilePkg.basename
TestImportTypeparamTests.list
TestIssue5815
time
TestImportTestdata.RangeStmt_3438.BlockStmt._
TestVersionHandling.RangeStmt_9081.BlockStmt._
TestImportedTypes.RangeStmt_13994.test
verifyInterfaceMethodRecvs.i
TestIssue13898.obj
TestIssue20046.index
testPath.t0
TestImportTypeparamTests.RangeStmt_5792.BlockStmt.BlockStmt.RangeStmt_7676.name
checkFile.src
TestIssue13566
TestIssue51836.dir
TestIssue51836.bpath
TestIssue51836.err
compile.dirname
TestImportTypeparamTests.tmpdir
TestImportStdLib.err
TestImportedTypes.RangeStmt_13994.BlockStmt.got
compilePkg.t
checkFile.fset
TestCorrectMethodPackage.err
TestIssue13898.m
TestImportTestdata.t
importPkg.pkg
lookupObj
lookupObj.name
checkFile.pkg
TestVersionHandling.RangeStmt_9081.BlockStmt.data
importObject.name
TestCorrectMethodPackage._
TestIssue15517.tmpdir
compileAndImportPkg.tmpdir
init
TestIssue5815.RangeStmt_17091.BlockStmt.BlockStmt.i
TestIssue13898.RangeStmt_20154.path
TestIssue57015
TestImportStdLib.out
TestIssue20046.indirect
apkg.testoutdir
importPkg.err
compile.packagefiles
compilePkg.BlockStmt.RangeStmt_2018.k
mktmpdir.err
TestImportTestdata.tmpdir
TestImportTypeparamTests.RangeStmt_5792.BlockStmt.BlockStmt.RangeStmt_6993.name
TestImportTypeparamTests.RangeStmt_5792.BlockStmt.BlockStmt.RangeStmt_6993.BlockStmt.want
TestImportStdLib.stderr
TestImportStdLib.pkgs
TestCorrectMethodPackage.t
TestCorrectMethodPackage.got
TestImportTypeparamTests.RangeStmt_5792.BlockStmt.BlockStmt.seen
TestIssue13898.t
TestImportTypeparamTests.RangeStmt_5792.entry
TestVersionHandling.list
TestIssue20046.obj
compilePkg
mktmpdir.t
TestImportedTypes.t
importObject
TestCorrectMethodPackage.sel
compilePkg.packagefiles
compilePkg.out
TestImportTypeparamTests.RangeStmt_5792.BlockStmt.BlockStmt.err
TestIssue13566.pkg
TestIssue13898.indirect
compilePkg.importcfgfile
TestCorrectMethodPackage.imports
TestIssue13566.jsonExport
importPkg.path
checkFile
TestIssue13898.goTypesPkg
TestImportTestdata.pkg
TestImportTypeparamTests
lookupObj.obj
compilePkg.BlockStmt.RangeStmt_2018.v
TestVersionHandling.err
verifyInterfaceMethodRecvs.BlockStmt.m
TestIssue15517.t
TestImportTestdata
goparser
compile.filename
TestVersionHandling.RangeStmt_9081.BlockStmt.err
lookupObj.scope
checkFile.f
TestIssue15920.t
TestImportTestdata.BlockStmt.RangeStmt_4494.want
TestImportTypeparamTests.RangeStmt_5792.BlockStmt.BlockStmt.pkgName
importObject.err
compileAndImportPkg.t
TestIssue13566.testoutdir
compile.t
TestImportTypeparamTests.RangeStmt_5792.BlockStmt.BlockStmt.filename
TestImportTypeparamTests.RangeStmt_5792.BlockStmt.BlockStmt.pkgFiles
TestImportTypeparamTests.RangeStmt_5792.BlockStmt.BlockStmt.checked
compileAndImportPkg.name
path
compile.outdirname
compilePkg.BlockStmt.err
TestCorrectMethodPackage.want
TestIssue15517.BlockStmt.err
testPath
TestVersionHandling.RangeStmt_9081.f
TestIssue15517.i
goimporter
TestIssue13566.bpath
TestIssue13898.imports
compilePkg.importreldir
testfile
TestImportedTypes
TestIssue13566._
TestIssue13898.err
TestMain.m
TestImportTypeparamTests.RangeStmt_5792.BlockStmt.BlockStmt.RangeStmt_6993.BlockStmt.importedObj
sanitizeObjectString.runes
TestVersionHandling.tmpdir
TestIssue20046.pkg
compilePkg.outname
TestCorrectMethodPackage.mutex
TestIssue51836.tmpdir
compilePkg.dirname
TestImportTypeparamTests.RangeStmt_5792.BlockStmt.BlockStmt.RangeStmt_6993.BlockStmt.checkedObj
TestVersionHandling.dir
goroot
TestImportTypeparamTests.err
TestImportedConsts.t
verifyInterfaceMethodRecvs.level
TestImportTestdata.BlockStmt.wants
TestImportTypeparamTests.t
TestImportTypeparamTests.RangeStmt_5792.BlockStmt.BlockStmt.src
checkFile.err
verifyInterfaceMethodRecvs.named
checkFile.config
importObject.pkg
sanitizeObjectString.s
TestImportedConsts.RangeStmt_14859.test
TestIssue5815.t
TestIssue13566.tmpdir
TestIssue13898
needsCompiler.compiler
TestVersionHandling.RangeStmt_9081.BlockStmt.msg
TestIssue20046.m
TestIssue51836.t
TestImportedConsts.RangeStmt_14859.BlockStmt.got
sanitizeObjectString.RangeStmt_8089.r
TestIssue5815.RangeStmt_17091.BlockStmt.BlockStmt.BlockStmt.m
compilePkg.err
TestImportTestdata.BlockStmt.got
TestImportedConsts.tests
TestIssue13898.RangeStmt_20154.pkg
TestIssue25301
testPath.srcDir
TestVersionHandling.corruptdir
verifyInterfaceMethodRecvs
TestIssue13566.t
TestIssue15517.imports
TestIssue51836
importPkg
testPath.err
TestCorrectMethodPackage
TestIssue57015.t
compilePkg.BlockStmt.importcfg
checkFile.filename
TestVersionHandling.t
TestIssue5815.scope
TestIssue15920
TestIssue51836.testoutdir
TestImportStdLib
init.BlockStmt.RangeStmt_13492.i
verifyInterfaceMethodRecvs.t
TestCorrectMethodPackage.mset
TestIssue13898.index
TestImportTypeparamTests.rootDir
sanitizeObjectString
checkFile.t
compile
TestImportTypeparamTests.RangeStmt_5792.BlockStmt.BlockStmt.imported
TestIssue13566.RangeStmt_19581.imp
testPath.t
TestImportTypeparamTests.RangeStmt_5792.BlockStmt.BlockStmt.RangeStmt_6993.BlockStmt.got
TestImportStdLib.t
TestImportStdLib.RangeStmt_11590.pkg
TestImportedConsts
importObject.t
compileAndImportPkg
TestVersionHandling.RangeStmt_9081.BlockStmt.name
TestImportStdLib.minPkgs
mktmpdir
TestIssue13898._
TestIssue15517.BlockStmt._
TestImportTestdata.RangeStmt_3438.BlockStmt.export
TestIssue20046
TestIssue25301.t
apkg
Members
X